[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
|
|
@ -21,15 +21,15 @@ export function AuthBanner(props: TAuthBanner) {
|
|||
return (
|
||||
<div
|
||||
role="alert"
|
||||
className="relative flex items-center p-2 rounded-md gap-2 border border-custom-primary-100/50 bg-custom-primary-100/10"
|
||||
className="relative flex items-center p-2 rounded-md gap-2 border border-accent-strong/50 bg-accent-primary/10"
|
||||
>
|
||||
<div className="size-4 flex-shrink-0 grid place-items-center">
|
||||
<Info size={16} className="text-custom-primary-100" />
|
||||
<Info size={16} className="text-accent-primary" />
|
||||
</div>
|
||||
<p className="w-full text-sm font-medium text-custom-primary-100">{bannerData?.message}</p>
|
||||
<p className="w-full text-13 font-medium text-accent-primary">{bannerData?.message}</p>
|
||||
<button
|
||||
type="button"
|
||||
className="relative ml-auto size-6 rounded-sm grid place-items-center transition-all hover:bg-custom-primary-100/20 text-custom-primary-100/80"
|
||||
className="relative ml-auto size-6 rounded-xs grid place-items-center transition-all hover:bg-accent-primary/20 text-accent-primary/80"
|
||||
onClick={() => handleBannerData?.(undefined)}
|
||||
aria-label={t("aria_labels.auth_forms.close_alert")}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -103,10 +103,8 @@ export const AuthHeader = observer(function AuthHeader(props: TAuthHeader) {
|
|||
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-2xl font-semibold text-custom-text-100 leading-7">
|
||||
{typeof header === "string" ? t(header) : header}
|
||||
</span>
|
||||
<span className="text-2xl font-semibold text-custom-text-400 leading-7">{subHeader}</span>
|
||||
<span className="text-h4-semibold text-primary">{typeof header === "string" ? t(header) : header}</span>
|
||||
<span className="text-h4-semibold text-placeholder">{subHeader}</span>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
export function AuthFormHeader({ title, description }: { title: string; description: string }) {
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-2xl font-semibold text-custom-text-100">{title}</span>
|
||||
<span className="text-2xl font-semibold text-custom-text-400">{description}</span>
|
||||
<span className="text-20 font-semibold text-primary">{title}</span>
|
||||
<span className="text-20 font-semibold text-placeholder">{description}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,13 +45,13 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
|||
return (
|
||||
<form onSubmit={handleFormSubmit} className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<label htmlFor="email" className="text-sm text-custom-text-300 font-medium">
|
||||
<label htmlFor="email" className="text-13 text-tertiary font-medium">
|
||||
{t("auth.common.email.label")}
|
||||
</label>
|
||||
<div
|
||||
className={cn(
|
||||
`relative flex items-center rounded-md bg-custom-background-100 border`,
|
||||
!isFocused && Boolean(emailError?.email) ? `border-red-500` : `border-custom-border-300`
|
||||
`relative flex items-center rounded-md bg-surface-1 border`,
|
||||
!isFocused && Boolean(emailError?.email) ? `border-red-500` : `border-strong`
|
||||
)}
|
||||
onFocus={() => {
|
||||
setIsFocused(true);
|
||||
|
|
@ -67,7 +67,7 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
|||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder={t("auth.common.email.placeholder")}
|
||||
className={`disable-autofill-style h-10 w-full placeholder:text-custom-text-400 autofill:bg-red-500 border-0 focus:bg-none active:bg-transparent`}
|
||||
className={`disable-autofill-style h-10 w-full placeholder:text-placeholder autofill:bg-red-500 border-0 focus:bg-none active:bg-transparent`}
|
||||
autoComplete="on"
|
||||
autoFocus
|
||||
ref={inputRef}
|
||||
|
|
@ -88,13 +88,13 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
|||
)}
|
||||
</div>
|
||||
{emailError?.email && !isFocused && (
|
||||
<p className="flex items-center gap-1 text-xs text-red-600 px-0.5">
|
||||
<p className="flex items-center gap-1 text-11 text-red-600 px-0.5">
|
||||
<CircleAlert height={12} width={12} />
|
||||
{t(emailError.email)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={isButtonDisabled}>
|
||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
||||
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("common.continue")}
|
||||
</Button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export function ForgotPasswordPopover() {
|
|||
<button
|
||||
type="button"
|
||||
ref={setReferenceElement}
|
||||
className="text-xs font-medium text-custom-primary-100 outline-none"
|
||||
className="text-11 font-medium text-accent-primary outline-none"
|
||||
>
|
||||
{t("auth.common.forgot_password")}
|
||||
</button>
|
||||
|
|
@ -38,20 +38,20 @@ export function ForgotPasswordPopover() {
|
|||
<Popover.Panel className="fixed z-10">
|
||||
{({ close }) => (
|
||||
<div
|
||||
className="border border-custom-border-300 bg-custom-background-100 rounded z-10 py-1 px-2 w-64 break-words flex items-start gap-3 text-left ml-3"
|
||||
className="border border-strong bg-surface-1 rounded-sm z-10 py-1 px-2 w-64 break-words flex items-start gap-3 text-left ml-3"
|
||||
ref={setPopperElement}
|
||||
style={styles.popper}
|
||||
{...attributes.popper}
|
||||
>
|
||||
<span className="flex-shrink-0">🤥</span>
|
||||
<p className="text-xs">{t("auth.forgot_password.errors.smtp_not_enabled")}</p>
|
||||
<p className="text-11">{t("auth.forgot_password.errors.smtp_not_enabled")}</p>
|
||||
<button
|
||||
type="button"
|
||||
className="flex-shrink-0 size-3 grid place-items-center"
|
||||
onClick={() => close()}
|
||||
aria-label={t("aria_labels.auth_forms.close_popover")}
|
||||
>
|
||||
<CloseIcon className="size-3 text-custom-text-200" />
|
||||
<CloseIcon className="size-3 text-secondary" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ export const ForgotPasswordForm = observer(function ForgotPasswordForm() {
|
|||
<AuthFormHeader title="Reset password" description="Regain access to your account." />
|
||||
<form onSubmit={handleSubmit(handleForgotPassword)} className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm font-medium text-custom-text-300" htmlFor="email">
|
||||
<label className="text-13 font-medium text-tertiary" htmlFor="email">
|
||||
{t("auth.common.email.label")}
|
||||
</label>
|
||||
<Controller
|
||||
|
|
@ -112,14 +112,14 @@ export const ForgotPasswordForm = observer(function ForgotPasswordForm() {
|
|||
ref={ref}
|
||||
hasError={Boolean(errors.email)}
|
||||
placeholder={t("auth.common.email.placeholder")}
|
||||
className="h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 placeholder:text-custom-text-400"
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 placeholder:text-placeholder"
|
||||
autoComplete="on"
|
||||
disabled={resendTimerCode > 0}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{resendTimerCode > 0 && (
|
||||
<p className="flex items-start w-full gap-1 px-1 text-xs font-medium text-green-700">
|
||||
<p className="flex items-start w-full gap-1 px-1 text-11 font-medium text-green-700">
|
||||
<CircleCheck height={12} width={12} className="mt-0.5" />
|
||||
{t("auth.forgot_password.email_sent")}
|
||||
</p>
|
||||
|
|
@ -129,7 +129,7 @@ export const ForgotPasswordForm = observer(function ForgotPasswordForm() {
|
|||
type="submit"
|
||||
variant="primary"
|
||||
className="w-full"
|
||||
size="lg"
|
||||
size="xl"
|
||||
disabled={!isValid}
|
||||
loading={isSubmitting || resendTimerCode > 0}
|
||||
>
|
||||
|
|
@ -137,7 +137,7 @@ export const ForgotPasswordForm = observer(function ForgotPasswordForm() {
|
|||
? t("auth.common.resend_in", { seconds: resendTimerCode })
|
||||
: t("auth.forgot_password.send_reset_link")}
|
||||
</Button>
|
||||
<Link href="/" className={cn("w-full", getButtonStyling("link-neutral", "lg"))}>
|
||||
<Link href="/" className={cn("w-full", getButtonStyling("link", "lg"))}>
|
||||
{t("auth.common.back_to_sign_in")}
|
||||
</Link>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
<Link
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.FORGOT_PASSWORD_FROM_SIGNIN}
|
||||
href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`}
|
||||
className="text-xs font-medium text-custom-primary-100"
|
||||
className="text-11 font-medium text-accent-primary"
|
||||
>
|
||||
{t("auth.common.forgot_password")}
|
||||
</Link>
|
||||
|
|
@ -128,9 +128,9 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
<div className="w-4 h-4 flex-shrink-0 relative flex justify-center items-center">
|
||||
<Info size={16} className="text-red-500" />
|
||||
</div>
|
||||
<div className="w-full text-sm font-medium text-red-500">{t("auth.sign_up.errors.password.strength")}</div>
|
||||
<div className="w-full text-13 font-medium text-red-500">{t("auth.sign_up.errors.password.strength")}</div>
|
||||
<div
|
||||
className="relative ml-auto w-6 h-6 rounded-sm flex justify-center items-center transition-all cursor-pointer hover:bg-red-500/20 text-custom-primary-100/80"
|
||||
className="relative ml-auto w-6 h-6 rounded-xs flex justify-center items-center transition-all cursor-pointer hover:bg-red-500/20 text-accent-primary/80"
|
||||
onClick={() => setBannerMessage(false)}
|
||||
>
|
||||
<CloseIcon className="w-4 h-4 flex-shrink-0 text-red-500" />
|
||||
|
|
@ -182,12 +182,10 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
<input type="hidden" value={passwordFormData.email} name="email" />
|
||||
{nextPath && <input type="hidden" value={nextPath} name="next_path" />}
|
||||
<div className="space-y-1">
|
||||
<label htmlFor="email" className="text-sm font-medium text-custom-text-300">
|
||||
<label htmlFor="email" className="text-13 font-medium text-tertiary">
|
||||
{t("auth.common.email.label")}
|
||||
</label>
|
||||
<div
|
||||
className={`relative flex items-center rounded-md bg-custom-background-100 border border-custom-border-300`}
|
||||
>
|
||||
<div className={`relative flex items-center rounded-md bg-surface-1 border border-strong`}>
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
|
|
@ -195,7 +193,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
value={passwordFormData.email}
|
||||
onChange={(e) => handleFormChange("email", e.target.value)}
|
||||
placeholder={t("auth.common.email.placeholder")}
|
||||
className={`disable-autofill-style h-10 w-full placeholder:text-custom-text-400 border-0`}
|
||||
className={`disable-autofill-style h-10 w-full placeholder:text-placeholder border-0`}
|
||||
disabled
|
||||
/>
|
||||
{passwordFormData.email.length > 0 && (
|
||||
|
|
@ -212,10 +210,10 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label htmlFor="password" className="text-sm text-custom-text-300 font-medium">
|
||||
<label htmlFor="password" className="text-13 text-tertiary font-medium">
|
||||
{mode === EAuthModes.SIGN_IN ? t("auth.common.password.label") : t("auth.common.password.set_password")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-custom-background-100">
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<Input
|
||||
type={showPassword?.password ? "text" : "password"}
|
||||
id="password"
|
||||
|
|
@ -223,7 +221,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
value={passwordFormData.password}
|
||||
onChange={(e) => handleFormChange("password", e.target.value)}
|
||||
placeholder={t("auth.common.password.placeholder")}
|
||||
className="disable-autofill-style h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 placeholder:text-custom-text-400"
|
||||
className="disable-autofill-style h-10 w-full border border-strong !bg-surface-1 pr-12 placeholder:text-placeholder"
|
||||
onFocus={() => setIsPasswordInputFocused(true)}
|
||||
onBlur={() => setIsPasswordInputFocused(false)}
|
||||
autoComplete="on"
|
||||
|
|
@ -249,10 +247,10 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
|
||||
{mode === EAuthModes.SIGN_UP && (
|
||||
<div className="space-y-1">
|
||||
<label htmlFor="confirm-password" className="text-sm text-custom-text-300 font-medium">
|
||||
<label htmlFor="confirm-password" className="text-13 text-tertiary font-medium">
|
||||
{t("auth.common.password.confirm_password.label")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-custom-background-100">
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<Input
|
||||
type={showPassword?.retypePassword ? "text" : "password"}
|
||||
id="confirm-password"
|
||||
|
|
@ -260,7 +258,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
value={passwordFormData.confirm_password}
|
||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||
placeholder={t("auth.common.password.confirm_password.placeholder")}
|
||||
className="disable-autofill-style h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 placeholder:text-custom-text-400"
|
||||
className="disable-autofill-style h-10 w-full border border-strong !bg-surface-1 pr-12 placeholder:text-placeholder"
|
||||
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||
/>
|
||||
|
|
@ -284,7 +282,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
{!!passwordFormData.confirm_password &&
|
||||
passwordFormData.password !== passwordFormData.confirm_password &&
|
||||
renderPasswordMatchError && (
|
||||
<span className="text-sm text-red-500">{t("auth.common.password.errors.match")}</span>
|
||||
<span className="text-13 text-red-500">{t("auth.common.password.errors.match")}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -292,7 +290,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
<div className="space-y-2.5">
|
||||
{mode === EAuthModes.SIGN_IN ? (
|
||||
<>
|
||||
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={isButtonDisabled}>
|
||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
||||
{isSubmitting ? (
|
||||
<Spinner height="20px" width="20px" />
|
||||
) : isSMTPConfigured ? (
|
||||
|
|
@ -306,16 +304,16 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
|||
type="button"
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.SIGN_IN_WITH_UNIQUE_CODE}
|
||||
onClick={redirectToUniqueCodeSignIn}
|
||||
variant="outline-primary"
|
||||
variant="secondary"
|
||||
className="w-full"
|
||||
size="lg"
|
||||
size="xl"
|
||||
>
|
||||
{t("auth.common.sign_in_with_unique_code")}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={isButtonDisabled}>
|
||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
||||
{isSubmitting ? <Spinner height="20px" width="20px" /> : "Create account"}
|
||||
</Button>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -105,10 +105,10 @@ export const ResetPasswordForm = observer(function ResetPasswordForm() {
|
|||
>
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-custom-text-300 font-medium" htmlFor="email">
|
||||
<label className="text-13 text-tertiary font-medium" htmlFor="email">
|
||||
{t("auth.common.email.label")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-custom-background-100">
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
|
|
@ -116,17 +116,17 @@ export const ResetPasswordForm = observer(function ResetPasswordForm() {
|
|||
value={resetFormData.email}
|
||||
//hasError={Boolean(errors.email)}
|
||||
placeholder={t("auth.common.email.placeholder")}
|
||||
className="h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 text-custom-text-400 cursor-not-allowed"
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 text-placeholder cursor-not-allowed"
|
||||
autoComplete="on"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-custom-text-300 font-medium" htmlFor="password">
|
||||
<label className="text-13 text-tertiary font-medium" htmlFor="password">
|
||||
{t("auth.common.password.label")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-custom-background-100">
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<Input
|
||||
type={showPassword.password ? "text" : "password"}
|
||||
name="password"
|
||||
|
|
@ -134,7 +134,7 @@ export const ResetPasswordForm = observer(function ResetPasswordForm() {
|
|||
onChange={(e) => handleFormChange("password", e.target.value)}
|
||||
//hasError={Boolean(errors.password)}
|
||||
placeholder={t("auth.common.password.placeholder")}
|
||||
className="h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 placeholder:text-custom-text-400"
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 placeholder:text-placeholder"
|
||||
minLength={8}
|
||||
onFocus={() => setIsPasswordInputFocused(true)}
|
||||
onBlur={() => setIsPasswordInputFocused(false)}
|
||||
|
|
@ -156,17 +156,17 @@ export const ResetPasswordForm = observer(function ResetPasswordForm() {
|
|||
<PasswordStrengthIndicator password={resetFormData.password} isFocused={isPasswordInputFocused} />
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-custom-text-300 font-medium" htmlFor="confirm_password">
|
||||
<label className="text-13 text-tertiary font-medium" htmlFor="confirm_password">
|
||||
{t("auth.common.password.confirm_password.label")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-custom-background-100">
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<Input
|
||||
type={showPassword.retypePassword ? "text" : "password"}
|
||||
name="confirm_password"
|
||||
value={resetFormData.confirm_password}
|
||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||
placeholder={t("auth.common.password.confirm_password.placeholder")}
|
||||
className="h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 placeholder:text-custom-text-400"
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 placeholder:text-placeholder"
|
||||
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||
/>
|
||||
|
|
@ -185,10 +185,10 @@ export const ResetPasswordForm = observer(function ResetPasswordForm() {
|
|||
{!!resetFormData.confirm_password &&
|
||||
resetFormData.password !== resetFormData.confirm_password &&
|
||||
renderPasswordMatchError && (
|
||||
<span className="text-sm text-red-500">{t("auth.common.password.errors.match")}</span>
|
||||
<span className="text-13 text-red-500">{t("auth.common.password.errors.match")}</span>
|
||||
)}
|
||||
</div>
|
||||
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={isButtonDisabled}>
|
||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
||||
{t("auth.common.password.submit")}
|
||||
</Button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -122,10 +122,10 @@ export const SetPasswordForm = observer(function SetPasswordForm() {
|
|||
<AuthFormHeader title="Set password" description="Create a new password." />
|
||||
<form className="space-y-4" onSubmit={(e) => handleSubmit(e)}>
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-custom-text-300 font-medium" htmlFor="email">
|
||||
<label className="text-13 text-tertiary font-medium" htmlFor="email">
|
||||
{t("auth.common.email.label")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-custom-background-100">
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
|
|
@ -133,17 +133,17 @@ export const SetPasswordForm = observer(function SetPasswordForm() {
|
|||
value={user?.email}
|
||||
//hasError={Boolean(errors.email)}
|
||||
placeholder={t("auth.common.email.placeholder")}
|
||||
className="h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 text-custom-text-400 cursor-not-allowed"
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 text-placeholder cursor-not-allowed"
|
||||
autoComplete="on"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-custom-text-300 font-medium" htmlFor="password">
|
||||
<label className="text-13 text-tertiary font-medium" htmlFor="password">
|
||||
{t("auth.common.password.label")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-custom-background-100">
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<Input
|
||||
type={showPassword.password ? "text" : "password"}
|
||||
name="password"
|
||||
|
|
@ -151,7 +151,7 @@ export const SetPasswordForm = observer(function SetPasswordForm() {
|
|||
onChange={(e) => handleFormChange("password", e.target.value)}
|
||||
//hasError={Boolean(errors.password)}
|
||||
placeholder={t("auth.common.password.placeholder")}
|
||||
className="h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 placeholder:text-custom-text-400"
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 placeholder:text-placeholder"
|
||||
minLength={8}
|
||||
onFocus={() => setIsPasswordInputFocused(true)}
|
||||
onBlur={() => setIsPasswordInputFocused(false)}
|
||||
|
|
@ -173,17 +173,17 @@ export const SetPasswordForm = observer(function SetPasswordForm() {
|
|||
<PasswordStrengthIndicator password={passwordFormData.password} isFocused={isPasswordInputFocused} />
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-custom-text-300 font-medium" htmlFor="confirm_password">
|
||||
<label className="text-13 text-tertiary font-medium" htmlFor="confirm_password">
|
||||
{t("auth.common.password.confirm_password.label")}
|
||||
</label>
|
||||
<div className="relative flex items-center rounded-md bg-custom-background-100">
|
||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
||||
<Input
|
||||
type={showPassword.retypePassword ? "text" : "password"}
|
||||
name="confirm_password"
|
||||
value={passwordFormData.confirm_password}
|
||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||
placeholder={t("auth.common.password.confirm_password.placeholder")}
|
||||
className="h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 placeholder:text-custom-text-400"
|
||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 placeholder:text-placeholder"
|
||||
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||
/>
|
||||
|
|
@ -202,10 +202,10 @@ export const SetPasswordForm = observer(function SetPasswordForm() {
|
|||
{!!passwordFormData.confirm_password &&
|
||||
passwordFormData.password !== passwordFormData.confirm_password &&
|
||||
renderPasswordMatchError && (
|
||||
<span className="text-sm text-red-500">{t("auth.common.password.errors.match")}</span>
|
||||
<span className="text-13 text-red-500">{t("auth.common.password.errors.match")}</span>
|
||||
)}
|
||||
</div>
|
||||
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={isButtonDisabled}>
|
||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
||||
{t("common.continue")}
|
||||
</Button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -115,12 +115,10 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {
|
|||
<input type="hidden" value={uniqueCodeFormData.email} name="email" />
|
||||
{nextPath && <input type="hidden" value={nextPath} name="next_path" />}
|
||||
<div className="space-y-1">
|
||||
<label htmlFor="email" className="text-sm font-medium text-custom-text-300">
|
||||
<label htmlFor="email" className="text-13 font-medium text-tertiary">
|
||||
{t("auth.common.email.label")}
|
||||
</label>
|
||||
<div
|
||||
className={`relative flex items-center rounded-md bg-custom-background-100 border border-custom-border-300`}
|
||||
>
|
||||
<div className={`relative flex items-center rounded-md bg-surface-1 border border-strong`}>
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
|
|
@ -128,7 +126,7 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {
|
|||
value={uniqueCodeFormData.email}
|
||||
onChange={(e) => handleFormChange("email", e.target.value)}
|
||||
placeholder={t("auth.common.email.placeholder")}
|
||||
className="disable-autofill-style h-10 w-full placeholder:text-custom-text-400 border-0"
|
||||
className="disable-autofill-style h-10 w-full placeholder:text-placeholder border-0"
|
||||
autoComplete="on"
|
||||
disabled
|
||||
/>
|
||||
|
|
@ -146,7 +144,7 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {
|
|||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label htmlFor="unique-code" className="text-sm font-medium text-custom-text-300">
|
||||
<label htmlFor="unique-code" className="text-13 font-medium text-tertiary">
|
||||
{t("auth.common.unique_code.label")}
|
||||
</label>
|
||||
<Input
|
||||
|
|
@ -155,10 +153,10 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {
|
|||
value={uniqueCodeFormData.code}
|
||||
onChange={(e) => handleFormChange("code", e.target.value)}
|
||||
placeholder={t("auth.common.unique_code.placeholder")}
|
||||
className="disable-autofill-style h-10 w-full border border-custom-border-300 !bg-custom-background-100 pr-12 placeholder:text-custom-text-400"
|
||||
className="disable-autofill-style h-10 w-full border border-strong !bg-surface-1 pr-12 placeholder:text-placeholder"
|
||||
autoFocus
|
||||
/>
|
||||
<div className="flex w-full items-center justify-between px-1 text-xs pt-1">
|
||||
<div className="flex w-full items-center justify-between px-1 text-11 pt-1">
|
||||
<p className="flex items-center gap-1 font-medium text-green-700">
|
||||
<CircleCheck height={12} width={12} />
|
||||
{t("auth.common.unique_code.paste_code")}
|
||||
|
|
@ -169,8 +167,8 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {
|
|||
onClick={() => generateNewCode(uniqueCodeFormData.email)}
|
||||
className={
|
||||
isRequestNewCodeDisabled
|
||||
? "text-custom-text-400"
|
||||
: "font-medium text-custom-primary-300 hover:text-custom-primary-200"
|
||||
? "text-placeholder"
|
||||
: "font-medium text-accent-secondary hover:text-accent-secondary"
|
||||
}
|
||||
disabled={isRequestNewCodeDisabled}
|
||||
>
|
||||
|
|
@ -188,7 +186,7 @@ export function AuthUniqueCodeForm(props: TAuthUniqueCodeForm) {
|
|||
type="submit"
|
||||
variant="primary"
|
||||
className="w-full"
|
||||
size="lg"
|
||||
size="xl"
|
||||
disabled={isButtonDisabled}
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.VERIFY_CODE}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export function DeactivateAccountModal(props: Props) {
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
|
||||
<div className="fixed inset-0 bg-backdrop transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-20 overflow-y-auto">
|
||||
|
|
@ -87,7 +87,7 @@ export function DeactivateAccountModal(props: Props) {
|
|||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-custom-background-100 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-[40rem]">
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-surface-1 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-[40rem]">
|
||||
<div className="px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
|
||||
<div className="">
|
||||
<div className="flex items-start gap-x-4">
|
||||
|
|
@ -98,10 +98,10 @@ export function DeactivateAccountModal(props: Props) {
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Dialog.Title as="h3" className="my-4 text-2xl font-medium leading-6 text-custom-text-100">
|
||||
<Dialog.Title as="h3" className="my-4 text-20 font-medium leading-6 text-primary">
|
||||
{t("deactivate_your_account")}
|
||||
</Dialog.Title>
|
||||
<p className="mt-6 list-disc pr-4 text-base font-normal text-custom-text-200">
|
||||
<p className="mt-6 list-disc pr-4 text-14 font-regular text-secondary">
|
||||
{t("deactivate_your_account_description")}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -109,10 +109,10 @@ export function DeactivateAccountModal(props: Props) {
|
|||
</div>
|
||||
</div>
|
||||
<div className="mb-2 flex items-center justify-end gap-2 p-4 sm:px-6">
|
||||
<Button variant="neutral-primary" onClick={onClose}>
|
||||
<Button variant="secondary" size="lg" onClick={onClose}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button variant="danger" onClick={handleDeleteAccount}>
|
||||
<Button variant="error-fill" size="lg" onClick={handleDeleteAccount}>
|
||||
{isDeactivating ? t("deactivating") : t("confirm")}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ const MESSAGES = {
|
|||
// Reusable link component to reduce duplication
|
||||
function LegalLink({ href, children }: { href: string; children: React.ReactNode }) {
|
||||
return (
|
||||
<Link href={href} className="text-custom-text-200" target="_blank" rel="noopener noreferrer">
|
||||
<span className="text-sm font-medium underline hover:cursor-pointer">{children}</span>
|
||||
<Link href={href} className="text-secondary" target="_blank" rel="noopener noreferrer">
|
||||
<span className="text-13 font-medium underline hover:cursor-pointer">{children}</span>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ function LegalLink({ href, children }: { href: string; children: React.ReactNode
|
|||
export function TermsAndConditions({ authType = EAuthModes.SIGN_IN }: TermsAndConditionsProps) {
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
<p className="text-center text-sm text-custom-text-300 whitespace-pre-line">
|
||||
<p className="text-center text-13 text-tertiary whitespace-pre-line">
|
||||
{`${MESSAGES[authType]}, you understand and agree to \n our `}
|
||||
<LegalLink href={LEGAL_LINKS.termsOfService}>Terms of Service</LegalLink> and{" "}
|
||||
<LegalLink href={LEGAL_LINKS.privacyPolicy}>Privacy Policy</LegalLink>.
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ function AnalyticsSectionWrapper(props: Props) {
|
|||
<div className={cn("mb-6 flex items-center gap-2 text-nowrap ", headerClassName)}>
|
||||
{title && (
|
||||
<div className="flex items-center gap-2 ">
|
||||
<h1 className={"text-lg font-medium"}>{title}</h1>
|
||||
{/* {subtitle && <p className="text-lg text-custom-text-300"> • {subtitle}</p>} */}
|
||||
<h1 className={"text-16 font-medium"}>{title}</h1>
|
||||
{/* {subtitle && <p className="text-16 text-tertiary"> • {subtitle}</p>} */}
|
||||
</div>
|
||||
)}
|
||||
{actions}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ function AnalyticsWrapper(props: Props) {
|
|||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className={cn("px-6 py-4", className)}>
|
||||
<h1 className={"mb-4 text-2xl font-bold md:mb-6"}>{t(i18nTitle)}</h1>
|
||||
<h1 className={"mb-4 text-20 font-bold md:mb-6"}>{t(i18nTitle)}</h1>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ function AnalyticsEmptyState({ title, description, assetPath, className }: Props
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-full w-full items-center justify-center overflow-y-auto rounded-lg border border-custom-border-100 px-5 py-10 md:px-20",
|
||||
"flex h-full w-full items-center justify-center overflow-y-auto rounded-lg border border-subtle px-5 py-10 md:px-20",
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
|
@ -34,8 +34,8 @@ function AnalyticsEmptyState({ title, description, assetPath, className }: Props
|
|||
</div>
|
||||
)}
|
||||
<div className="flex flex-shrink flex-col items-center gap-1.5 text-center">
|
||||
<h3 className={cn("text-xl font-semibold")}>{title}</h3>
|
||||
{description && <p className="text-sm text-custom-text-300 max-w-[350px]">{description}</p>}
|
||||
<h3 className={cn("text-18 font-semibold")}>{title}</h3>
|
||||
{description && <p className="text-13 text-tertiary max-w-[350px]">{description}</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ function InsightCard(props: InsightCardProps) {
|
|||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="text-sm text-custom-text-300">{label}</div>
|
||||
<div className="text-13 text-tertiary">{label}</div>
|
||||
{!isLoading ? (
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="text-2xl font-bold text-custom-text-100">{count}</div>
|
||||
<div className="text-20 font-bold text-primary">{count}</div>
|
||||
</div>
|
||||
) : (
|
||||
<Loader.Item height="50px" width="100%" />
|
||||
|
|
|
|||
|
|
@ -63,14 +63,14 @@ export function DataTable<TData, TValue>({ columns, data, searchPlaceholder, act
|
|||
<div className="flex w-full items-center justify-between">
|
||||
<div className="relative flex max-w-[300px] items-center gap-4 ">
|
||||
{table.getHeaderGroups()?.[0]?.headers?.[0]?.id && (
|
||||
<div className="flex items-center gap-2 whitespace-nowrap text-sm text-custom-text-400">
|
||||
<div className="flex items-center gap-2 whitespace-nowrap text-13 text-placeholder">
|
||||
{searchPlaceholder}
|
||||
</div>
|
||||
)}
|
||||
{!isSearchOpen && (
|
||||
<button
|
||||
type="button"
|
||||
className="-mr-5 grid place-items-center rounded p-2 text-custom-text-400 hover:bg-custom-background-80"
|
||||
className="-mr-5 grid place-items-center rounded-sm p-2 text-placeholder hover:bg-layer-1"
|
||||
onClick={() => {
|
||||
setIsSearchOpen(true);
|
||||
inputRef.current?.focus();
|
||||
|
|
@ -81,16 +81,16 @@ export function DataTable<TData, TValue>({ columns, data, searchPlaceholder, act
|
|||
)}
|
||||
<div
|
||||
className={cn(
|
||||
"mr-auto flex w-0 items-center justify-start gap-1 overflow-hidden rounded-md border border-transparent bg-custom-background-100 text-custom-text-400 opacity-0 transition-[width] ease-linear",
|
||||
"mr-auto flex w-0 items-center justify-start gap-1 overflow-hidden rounded-md border border-transparent bg-surface-1 text-placeholder opacity-0 transition-[width] ease-linear",
|
||||
{
|
||||
"w-64 border-custom-border-200 px-2.5 py-1.5 opacity-100": isSearchOpen,
|
||||
"w-64 border-subtle px-2.5 py-1.5 opacity-100": isSearchOpen,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<Search className="h-3.5 w-3.5" />
|
||||
<input
|
||||
ref={inputRef}
|
||||
className="w-full max-w-[234px] border-none bg-transparent text-sm text-custom-text-100 placeholder:text-custom-text-400 focus:outline-none"
|
||||
className="w-full max-w-[234px] border-none bg-transparent text-13 text-primary placeholder:text-placeholder focus:outline-none"
|
||||
placeholder="Search"
|
||||
value={table.getColumn(table.getHeaderGroups()?.[0]?.headers?.[0]?.id)?.getFilterValue() as string}
|
||||
onChange={(e) => {
|
||||
|
|
@ -155,7 +155,7 @@ export function DataTable<TData, TValue>({ columns, data, searchPlaceholder, act
|
|||
<EmptyStateCompact
|
||||
assetKey="unknown"
|
||||
assetClassName="size-20"
|
||||
rootClassName="border border-custom-border-100 px-5 py-10 md:py-20 md:px-20"
|
||||
rootClassName="border border-subtle px-5 py-10 md:py-20 md:px-20"
|
||||
title={t("workspace_empty_state.analytics_work_items.title")}
|
||||
/>
|
||||
</TableCell>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export function InsightTable<T extends Exclude<TAnalyticsTabsBase, "overview">>(
|
|||
searchPlaceholder={`${data?.length || 0} ${headerText}`}
|
||||
actions={(table: Table<AnalyticsTableDataMap[T]>) => (
|
||||
<Button
|
||||
variant="accent-primary"
|
||||
variant="secondary"
|
||||
prependIcon={<Download className="h-3.5 w-3.5" />}
|
||||
onClick={() => onExport?.(table.getFilteredRowModel().rows)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ type Props = {
|
|||
function CompletionPercentage({ percentage }: { percentage: number }) {
|
||||
const percentageColor = percentage > 50 ? "bg-green-500/30 text-green-500" : "bg-red-500/30 text-red-500";
|
||||
return (
|
||||
<div className={cn("flex items-center gap-2 rounded p-1 text-xs", percentageColor)}>
|
||||
<div className={cn("flex items-center gap-2 rounded-sm p-1 text-11", percentageColor)}>
|
||||
<span>{percentage}%</span>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -36,7 +36,7 @@ function ActiveProjectItem(props: Props) {
|
|||
return (
|
||||
<div className="flex items-center justify-between gap-2 w-full">
|
||||
<div className="flex items-center gap-2 flex-1 overflow-hidden">
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-xl bg-custom-background-80 shrink-0">
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-xl bg-layer-1 shrink-0">
|
||||
<span className="grid h-4 w-4 flex-shrink-0 place-items-center">
|
||||
{projectDetails?.logo_props ? (
|
||||
<Logo logo={projectDetails?.logo_props} size={16} />
|
||||
|
|
@ -48,7 +48,7 @@ function ActiveProjectItem(props: Props) {
|
|||
</span>
|
||||
</div>
|
||||
<Tooltip tooltipContent={projectDetails?.name} position="top-start">
|
||||
<p className="text-sm font-medium truncate">{projectDetails?.name}</p>
|
||||
<p className="text-13 font-medium truncate">{projectDetails?.name}</p>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<CompletionPercentage
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ const ProjectInsights = observer(function ProjectInsights() {
|
|||
<EmptyStateCompact
|
||||
assetKey="unknown"
|
||||
assetClassName="size-20"
|
||||
rootClassName="border border-custom-border-100 px-5 py-10 md:py-20 md:px-20"
|
||||
rootClassName="border border-subtle px-5 py-10 md:py-20 md:px-20"
|
||||
title={t("workspace_empty_state.analytics_work_items.title")}
|
||||
/>
|
||||
) : (
|
||||
|
|
@ -90,19 +90,19 @@ const ProjectInsights = observer(function ProjectInsights() {
|
|||
</Suspense>
|
||||
)}
|
||||
<div className="w-full lg:w-2/5">
|
||||
<div className="text-sm text-custom-text-300">{t("workspace_analytics.summary_of_projects")}</div>
|
||||
<div className=" mb-3 border-b border-custom-border-100 py-2">{t("workspace_analytics.all_projects")}</div>
|
||||
<div className="text-13 text-tertiary">{t("workspace_analytics.summary_of_projects")}</div>
|
||||
<div className=" mb-3 border-b border-subtle py-2">{t("workspace_analytics.all_projects")}</div>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex items-center justify-between text-sm text-custom-text-300">
|
||||
<div className="flex items-center justify-between text-13 text-tertiary">
|
||||
<div>{t("workspace_analytics.trend_on_charts")}</div>
|
||||
<div>{t("common.work_items")}</div>
|
||||
</div>
|
||||
{projectInsightsData?.map((item) => (
|
||||
<div key={item.key} className="flex items-center justify-between text-sm text-custom-text-100">
|
||||
<div key={item.key} className="flex items-center justify-between text-13 text-primary">
|
||||
<div>{item.name}</div>
|
||||
<div className="flex items-center gap-1">
|
||||
{/* <TrendPiece key={item.key} size='xs' /> */}
|
||||
<div className="text-custom-text-200">{item.count}</div>
|
||||
<div className="text-secondary">{item.count}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ import { useMemo } from "react";
|
|||
import { observer } from "mobx-react";
|
||||
import type { Control, UseFormSetValue } from "react-hook-form";
|
||||
import { Controller } from "react-hook-form";
|
||||
import { Calendar, SlidersHorizontal } from "lucide-react";
|
||||
import { SlidersHorizontal } from "lucide-react";
|
||||
// plane package imports
|
||||
import { ANALYTICS_X_AXIS_VALUES, ANALYTICS_Y_AXIS_VALUES } from "@plane/constants";
|
||||
import { CalendarLayoutIcon } from "@plane/propel/icons";
|
||||
import type { IAnalyticsParams } from "@plane/types";
|
||||
import { ChartYAxisMetric } from "@plane/types";
|
||||
import { cn } from "@plane/utils";
|
||||
|
|
@ -63,8 +64,8 @@ export const AnalyticsSelectParams = observer(function AnalyticsSelectParams(pro
|
|||
}}
|
||||
label={
|
||||
<div className="flex items-center gap-2">
|
||||
<Calendar className="h-3 w-3" />
|
||||
<span className={cn("text-custom-text-200", value && "text-custom-text-100")}>
|
||||
<CalendarLayoutIcon className="h-3 w-3" />
|
||||
<span className={cn("text-secondary", value && "text-primary")}>
|
||||
{xAxisOptions.find((v) => v.value === value)?.label || "Add Property"}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -85,7 +86,7 @@ export const AnalyticsSelectParams = observer(function AnalyticsSelectParams(pro
|
|||
label={
|
||||
<div className="flex items-center gap-2">
|
||||
<SlidersHorizontal className="h-3 w-3" />
|
||||
<span className={cn("text-custom-text-200", value && "text-custom-text-100")}>
|
||||
<span className={cn("text-secondary", value && "text-primary")}>
|
||||
{groupByOptions.find((v) => v.value === value)?.label || "Add Property"}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,19 +14,19 @@ type Props = {
|
|||
|
||||
const sizeConfig = {
|
||||
xs: {
|
||||
text: "text-xs",
|
||||
text: "text-11",
|
||||
icon: "w-3 h-3",
|
||||
},
|
||||
sm: {
|
||||
text: "text-sm",
|
||||
text: "text-13",
|
||||
icon: "w-4 h-4",
|
||||
},
|
||||
md: {
|
||||
text: "text-base",
|
||||
text: "text-14",
|
||||
icon: "w-5 h-5",
|
||||
},
|
||||
lg: {
|
||||
text: "text-lg",
|
||||
text: "text-16",
|
||||
icon: "w-6 h-6",
|
||||
},
|
||||
} as const;
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ const CreatedVsResolved = observer(function CreatedVsResolved() {
|
|||
<EmptyStateCompact
|
||||
assetKey="unknown"
|
||||
assetClassName="size-20"
|
||||
rootClassName="border border-custom-border-100 px-5 py-10 md:py-20 md:px-20"
|
||||
rootClassName="border border-subtle px-5 py-10 md:py-20 md:px-20"
|
||||
title={t("workspace_empty_state.analytics_work_items.title")}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -18,21 +18,21 @@ export const WorkItemsModalHeader = observer(function WorkItemsModalHeader(props
|
|||
const { fullScreen, handleClose, setFullScreen, title, cycle, module } = props;
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-4 bg-custom-background-100 px-5 py-4 text-sm">
|
||||
<div className="flex items-center justify-between gap-4 bg-surface-1 px-5 py-4 text-13">
|
||||
<h3 className="break-words">
|
||||
Analytics for {title} {cycle && `in ${cycle.name}`} {module && `in ${module.name}`}
|
||||
</h3>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="hidden place-items-center p-1 text-custom-text-200 hover:text-custom-text-100 md:grid"
|
||||
className="hidden place-items-center p-1 text-secondary hover:text-primary md:grid"
|
||||
onClick={() => setFullScreen((prevData) => !prevData)}
|
||||
>
|
||||
{fullScreen ? <Shrink size={14} strokeWidth={2} /> : <Expand size={14} strokeWidth={2} />}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="grid place-items-center p-1 text-custom-text-200 hover:text-custom-text-100"
|
||||
className="grid place-items-center p-1 text-secondary hover:text-primary"
|
||||
onClick={handleClose}
|
||||
>
|
||||
<CloseIcon height={14} width={14} strokeWidth={2} />
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export const WorkItemsModal = observer(function WorkItemsModal(props: Props) {
|
|||
fullScreen={fullScreen}
|
||||
>
|
||||
<div
|
||||
className={`flex h-full flex-col overflow-hidden border-custom-border-200 bg-custom-background-100 text-left ${
|
||||
className={`flex h-full flex-col overflow-hidden border-subtle bg-surface-1 text-left ${
|
||||
fullScreen ? "rounded-lg border" : "border-l"
|
||||
}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ const PriorityChart = observer(function PriorityChart(props: Props) {
|
|||
searchPlaceholder={`${parsedData.data.length} ${xAxisLabel}`}
|
||||
actions={(table: Table<TChartDatum>) => (
|
||||
<Button
|
||||
variant="accent-primary"
|
||||
variant="secondary"
|
||||
prependIcon={<Download className="h-3.5 w-3.5" />}
|
||||
onClick={() => exportCSV(table.getRowModel().rows, [...defaultColumns, ...columns], workspaceSlug)}
|
||||
>
|
||||
|
|
@ -233,7 +233,7 @@ const PriorityChart = observer(function PriorityChart(props: Props) {
|
|||
<EmptyStateCompact
|
||||
assetKey="unknown"
|
||||
assetClassName="size-20"
|
||||
rootClassName="border border-custom-border-100 px-5 py-10 md:py-20 md:px-20"
|
||||
rootClassName="border border-subtle px-5 py-10 md:py-20 md:px-20"
|
||||
title={t("workspace_empty_state.analytics_work_items.title")}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -110,17 +110,15 @@ const WorkItemsInsightTable = observer(function WorkItemsInsightTable() {
|
|||
shape="circle"
|
||||
/>
|
||||
) : (
|
||||
<div className="flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-custom-background-80 capitalize overflow-hidden">
|
||||
<div className="flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full bg-layer-1 capitalize overflow-hidden">
|
||||
{row.original.display_name ? (
|
||||
row.original.display_name?.[0]
|
||||
) : (
|
||||
<UserRound className="text-custom-text-200 " size={12} />
|
||||
<UserRound className="text-secondary " size={12} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<span className="break-words text-custom-text-200">
|
||||
{row.original.display_name ?? t(`Unassigned`)}
|
||||
</span>
|
||||
<span className="break-words text-secondary">{row.original.display_name ?? t(`Unassigned`)}</span>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ export function ApiTokenEmptyState(props: Props) {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`mx-auto flex w-full items-center justify-center rounded-sm border border-custom-border-200 bg-custom-background-90 px-16 py-10 lg:w-3/4`}
|
||||
className={`mx-auto flex w-full items-center justify-center rounded-xs border border-subtle bg-surface-2 px-16 py-10 lg:w-3/4`}
|
||||
>
|
||||
<div className="flex w-full flex-col items-center text-center">
|
||||
<img src={emptyApiTokens} className="w-52 sm:w-60 object-contain" alt="empty" />
|
||||
<h6 className="mb-3 mt-6 text-xl font-semibold sm:mt-8">No API tokens</h6>
|
||||
<p className="mb-7 text-custom-text-300 sm:mb-8">
|
||||
<h6 className="mb-3 mt-6 text-18 font-semibold sm:mt-8">No API tokens</h6>
|
||||
<p className="mb-7 text-tertiary sm:mb-8">
|
||||
Create API tokens for safe and easy data sharing with external apps, maintaining control and security.
|
||||
</p>
|
||||
<Button className="flex items-center gap-1.5" onClick={onClick}>
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ export function CreateApiTokenForm(props: Props) {
|
|||
return (
|
||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
||||
<div className="space-y-5 p-5">
|
||||
<h3 className="text-xl font-medium text-custom-text-200">
|
||||
<h3 className="text-18 font-medium text-secondary">
|
||||
{t("workspace_settings.settings.api_tokens.create_token")}
|
||||
</h3>
|
||||
<div className="space-y-3">
|
||||
|
|
@ -143,11 +143,11 @@ export function CreateApiTokenForm(props: Props) {
|
|||
onChange={onChange}
|
||||
hasError={Boolean(errors.label)}
|
||||
placeholder={t("title")}
|
||||
className="w-full text-base"
|
||||
className="w-full text-14"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors.label && <span className="text-xs text-red-500">{errors.label.message}</span>}
|
||||
{errors.label && <span className="text-11 text-red-500">{errors.label.message}</span>}
|
||||
</div>
|
||||
<Controller
|
||||
control={control}
|
||||
|
|
@ -158,7 +158,7 @@ export function CreateApiTokenForm(props: Props) {
|
|||
onChange={onChange}
|
||||
hasError={Boolean(errors.description)}
|
||||
placeholder={t("description")}
|
||||
className="w-full text-base resize-none min-h-24"
|
||||
className="w-full text-14 resize-none min-h-24"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
@ -175,9 +175,9 @@ export function CreateApiTokenForm(props: Props) {
|
|||
customButton={
|
||||
<div
|
||||
className={cn(
|
||||
"h-7 flex items-center gap-2 rounded border-[0.5px] border-custom-border-300 px-2 py-0.5",
|
||||
"h-7 flex items-center gap-2 rounded-sm border-[0.5px] border-strong px-2 py-0.5",
|
||||
{
|
||||
"text-custom-text-400": neverExpires,
|
||||
"text-placeholder": neverExpires,
|
||||
}
|
||||
)}
|
||||
>
|
||||
|
|
@ -218,7 +218,7 @@ export function CreateApiTokenForm(props: Props) {
|
|||
)}
|
||||
</div>
|
||||
{!neverExpires && (
|
||||
<span className="text-xs text-custom-text-400">
|
||||
<span className="text-11 text-placeholder">
|
||||
{expiredAt === "custom"
|
||||
? customDate
|
||||
? `Expires ${renderFormattedDate(customDateFormatted ?? "")} at ${renderFormattedTime(customDateFormatted ?? "")}`
|
||||
|
|
@ -231,18 +231,18 @@ export function CreateApiTokenForm(props: Props) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-5 py-4 flex items-center justify-between gap-2 border-t-[0.5px] border-custom-border-200">
|
||||
<div className="px-5 py-4 flex items-center justify-between gap-2 border-t-[0.5px] border-subtle">
|
||||
<div className="flex cursor-pointer items-center gap-1.5" onClick={toggleNeverExpires}>
|
||||
<div className="flex cursor-pointer items-center justify-center">
|
||||
<ToggleSwitch value={neverExpires} onChange={() => {}} size="sm" />
|
||||
</div>
|
||||
<span className="text-xs">{t("workspace_settings.settings.api_tokens.never_expires")}</span>
|
||||
<span className="text-11">{t("workspace_settings.settings.api_tokens.never_expires")}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
<Button variant="secondary" onClick={handleClose}>
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
<Button variant="primary" size="sm" type="submit" loading={isSubmitting}>
|
||||
<Button variant="primary" type="submit" loading={isSubmitting}>
|
||||
{isSubmitting
|
||||
? t("workspace_settings.settings.api_tokens.generating")
|
||||
: t("workspace_settings.settings.api_tokens.generate_token")}
|
||||
|
|
|
|||
|
|
@ -33,26 +33,26 @@ export function GeneratedTokenDetails(props: Props) {
|
|||
return (
|
||||
<div className="w-full p-5">
|
||||
<div className="w-full space-y-3 text-wrap">
|
||||
<h3 className="text-lg font-medium leading-6 text-custom-text-100">{t("workspace_settings.key_created")}</h3>
|
||||
<p className="text-sm text-custom-text-400">{t("workspace_settings.copy_key")}</p>
|
||||
<h3 className="text-16 font-medium leading-6 text-primary">{t("workspace_settings.key_created")}</h3>
|
||||
<p className="text-13 text-placeholder">{t("workspace_settings.copy_key")}</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyApiToken(tokenDetails.token ?? "")}
|
||||
className="mt-4 flex truncate w-full items-center justify-between rounded-md border-[0.5px] border-custom-border-200 px-3 py-2 text-sm font-medium outline-none"
|
||||
className="mt-4 flex truncate w-full items-center justify-between rounded-md border-[0.5px] border-subtle px-3 py-2 text-13 font-medium outline-none"
|
||||
>
|
||||
<span className="truncate pr-2">{tokenDetails.token}</span>
|
||||
<Tooltip tooltipContent="Copy secret key" isMobile={isMobile}>
|
||||
<Copy className="h-4 w-4 text-custom-text-400 flex-shrink-0" />
|
||||
<Copy className="h-4 w-4 text-placeholder flex-shrink-0" />
|
||||
</Tooltip>
|
||||
</button>
|
||||
<div className="mt-6 flex items-center justify-between">
|
||||
<p className="text-xs text-custom-text-400">
|
||||
<p className="text-11 text-placeholder">
|
||||
{tokenDetails.expired_at
|
||||
? `Expires ${renderFormattedDate(tokenDetails.expired_at)} at ${renderFormattedTime(tokenDetails.expired_at)}`
|
||||
: "Never expires"}
|
||||
</p>
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
<Button variant="secondary" onClick={handleClose}>
|
||||
{t("close")}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export function ApiTokenListItem(props: Props) {
|
|||
return (
|
||||
<>
|
||||
<DeleteApiTokenModal isOpen={deleteModalOpen} onClose={() => setDeleteModalOpen(false)} tokenId={token.id} />
|
||||
<div className="group relative flex flex-col justify-center border-b border-custom-border-200 py-3">
|
||||
<div className="group relative flex flex-col justify-center border-b border-subtle py-3">
|
||||
<Tooltip tooltipContent="Delete token" isMobile={isMobile}>
|
||||
<button
|
||||
onClick={() => setDeleteModalOpen(true)}
|
||||
|
|
@ -35,20 +35,20 @@ export function ApiTokenListItem(props: Props) {
|
|||
</button>
|
||||
</Tooltip>
|
||||
<div className="flex w-4/5 items-center">
|
||||
<h5 className="truncate text-sm font-medium">{token.label}</h5>
|
||||
<h5 className="truncate text-13 font-medium">{token.label}</h5>
|
||||
<span
|
||||
className={`${
|
||||
token.is_active ? "bg-green-500/10 text-green-500" : "bg-custom-background-80 text-custom-text-400"
|
||||
} ml-2 flex h-4 max-h-fit items-center rounded-sm px-2 text-xs font-medium`}
|
||||
token.is_active ? "bg-green-500/10 text-green-500" : "bg-layer-1 text-placeholder"
|
||||
} ml-2 flex h-4 max-h-fit items-center rounded-xs px-2 text-11 font-medium`}
|
||||
>
|
||||
{token.is_active ? "Active" : "Expired"}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-1 flex w-full flex-col justify-center">
|
||||
{token.description.trim() !== "" && (
|
||||
<p className="mb-1 max-w-[70%] break-words text-sm">{token.description}</p>
|
||||
<p className="mb-1 max-w-[70%] break-words text-13">{token.description}</p>
|
||||
)}
|
||||
<p className="mb-1 text-xs leading-6 text-custom-text-400">
|
||||
<p className="mb-1 text-11 leading-6 text-placeholder">
|
||||
{token.is_active
|
||||
? token.expired_at
|
||||
? `Expires ${renderFormattedDate(token.expired_at)} at ${renderFormattedTime(token.expired_at)}`
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ export const ArchiveTabsList = observer(function ArchiveTabsList() {
|
|||
tab.shouldRender(projectDetails) && (
|
||||
<Link key={tab.key} href={`/${workspaceSlug}/projects/${projectId}/archives/${tab.key}`}>
|
||||
<span
|
||||
className={`flex min-w-min flex-shrink-0 whitespace-nowrap border-b-2 py-4 px-4 text-sm font-medium outline-none ${
|
||||
className={`flex min-w-min flex-shrink-0 whitespace-nowrap border-b-2 py-4 px-4 text-13 font-medium outline-none ${
|
||||
pathname.includes(tab.key)
|
||||
? "border-custom-primary-100 text-custom-primary-100"
|
||||
: "border-transparent hover:border-custom-border-200 text-custom-text-300 hover:text-custom-text-400"
|
||||
? "border-accent-strong text-accent-primary"
|
||||
: "border-transparent hover:border-subtle text-tertiary hover:text-placeholder"
|
||||
}`}
|
||||
>
|
||||
{tab.label}
|
||||
|
|
|
|||
|
|
@ -11,22 +11,22 @@ const BRAND_LOGOS: {
|
|||
},
|
||||
{
|
||||
id: "sony",
|
||||
icon: <SonyLogo className="h-7 w-16 dark:text-white" />,
|
||||
icon: <SonyLogo className="h-7 w-16 dark:text-on-color" />,
|
||||
},
|
||||
{
|
||||
id: "dolby",
|
||||
icon: <DolbyLogo className="h-7 w-16 dark:text-white" />,
|
||||
icon: <DolbyLogo className="h-7 w-16 dark:text-on-color" />,
|
||||
},
|
||||
{
|
||||
id: "accenture",
|
||||
icon: <AccentureLogo className="h-7 w-24 dark:text-white" />,
|
||||
icon: <AccentureLogo className="h-7 w-24 dark:text-on-color" />,
|
||||
},
|
||||
];
|
||||
|
||||
export function AuthFooter() {
|
||||
return (
|
||||
<div className="flex flex-col items-center gap-6">
|
||||
<span className="text-sm text-custom-text-300 whitespace-nowrap">Join 10,000+ teams building with Plane</span>
|
||||
<span className="text-13 text-tertiary whitespace-nowrap">Join 10,000+ teams building with Plane</span>
|
||||
<div className="flex items-center justify-center gap-x-10 gap-y-4 w-full flex-wrap">
|
||||
{BRAND_LOGOS.map((brand) => (
|
||||
<div className="flex items-center justify-center h-7 flex-1" key={brand.id}>
|
||||
|
|
|
|||
|
|
@ -38,15 +38,15 @@ export const AuthHeader = observer(function AuthHeader({ type }: AuthHeaderProps
|
|||
<PageHead title={t(authContentMap[type].pageTitle) + " - Plane"} />
|
||||
<div className="flex items-center justify-between gap-6 w-full flex-shrink-0 sticky top-0">
|
||||
<Link href="/">
|
||||
<PlaneLockup height={20} width={95} className="text-custom-text-100" />
|
||||
<PlaneLockup height={20} width={95} className="text-primary" />
|
||||
</Link>
|
||||
{enableSignUpConfig && (
|
||||
<div className="flex flex-col items-end text-sm font-medium text-center sm:items-center sm:gap-2 sm:flex-row text-custom-text-300">
|
||||
{t(authContentMap[type].text)}
|
||||
<div className="flex flex-col items-end text-13 font-medium text-center sm:items-center sm:gap-2 sm:flex-row text-tertiary">
|
||||
<span className="text-body-sm-regular text-tertiary">{t(authContentMap[type].text)}</span>
|
||||
<Link
|
||||
data-ph-element={AUTH_TRACKER_ELEMENTS.NAVIGATE_TO_SIGN_UP}
|
||||
href={authContentMap[type].linkHref}
|
||||
className="font-semibold text-custom-primary-100 hover:underline"
|
||||
className="text-body-sm-semibold text-accent-primary hover:underline"
|
||||
>
|
||||
{t(authContentMap[type].linkText)}
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ export const NotAuthorizedView = observer(function NotAuthorizedView(props: Prop
|
|||
|
||||
return (
|
||||
<DefaultLayout className={className}>
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-y-5 bg-custom-background-100 text-center">
|
||||
<div className="flex h-full w-full flex-col items-center justify-center gap-y-5 bg-surface-1 text-center">
|
||||
<div className="h-44 w-72">
|
||||
<img src={asset} className="h-[176px] w-[288px] object-contain" alt="ProjectSettingImg" />
|
||||
</div>
|
||||
<h1 className="text-xl font-medium text-custom-text-100">Oops! You are not authorized to view this page</h1>
|
||||
<h1 className="text-18 font-medium text-primary">Oops! You are not authorized to view this page</h1>
|
||||
{actionButton}
|
||||
</div>
|
||||
</DefaultLayout>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export const ProjectAccessRestriction = observer(function ProjectAccessRestricti
|
|||
// - User lacks permission to access the private project (403 Forbidden) but is a workspace admin (can join any project)
|
||||
if (errorStatusCode === 409 || (errorStatusCode === 403 && isWorkspaceAdmin))
|
||||
return (
|
||||
<div className="grid h-full w-full place-items-center bg-custom-background-100">
|
||||
<div className="grid h-full w-full place-items-center bg-surface-1">
|
||||
<EmptyStateDetailed
|
||||
title={t("project_empty_state.no_access.title")}
|
||||
description={t("project_empty_state.no_access.join_description")}
|
||||
|
|
@ -43,7 +43,7 @@ export const ProjectAccessRestriction = observer(function ProjectAccessRestricti
|
|||
// - User lacks permission to access the private project (403 Forbidden)
|
||||
if (errorStatusCode === 403) {
|
||||
return (
|
||||
<div className="grid h-full w-full place-items-center bg-custom-background-100">
|
||||
<div className="grid h-full w-full place-items-center bg-surface-1">
|
||||
<EmptyStateDetailed
|
||||
title={t("project_empty_state.no_access.title")}
|
||||
description={t("project_empty_state.no_access.restricted_description")}
|
||||
|
|
@ -58,7 +58,7 @@ export const ProjectAccessRestriction = observer(function ProjectAccessRestricti
|
|||
// - Project not found (404 Not Found)
|
||||
// - Any other error status code
|
||||
return (
|
||||
<div className="grid h-full w-full place-items-center bg-custom-background-100">
|
||||
<div className="grid h-full w-full place-items-center bg-surface-1">
|
||||
<EmptyStateDetailed
|
||||
title={t("project_empty_state.invalid_project.title")}
|
||||
description={t("project_empty_state.invalid_project.description")}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ export function NotAWorkspaceMember() {
|
|||
<div className="grid h-full place-items-center p-4">
|
||||
<div className="space-y-8 text-center">
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-lg font-semibold">Not Authorized!</h3>
|
||||
<p className="mx-auto w-1/2 text-sm text-custom-text-200">
|
||||
<h3 className="text-16 font-semibold">Not Authorized!</h3>
|
||||
<p className="mx-auto w-1/2 text-13 text-secondary">
|
||||
You{"'"}re not a member of this workspace. Please contact the workspace admin to get an invitation or
|
||||
check your pending invitations.
|
||||
</p>
|
||||
|
|
@ -19,7 +19,7 @@ export function NotAWorkspaceMember() {
|
|||
<div className="flex items-center justify-center gap-2">
|
||||
<Link href="/invitations">
|
||||
<span>
|
||||
<Button variant="neutral-primary">Check pending invites</Button>
|
||||
<Button variant="secondary">Check pending invites</Button>
|
||||
</span>
|
||||
</Link>
|
||||
<Link href="/create-workspace">
|
||||
|
|
|
|||
|
|
@ -61,15 +61,15 @@ export const AutoArchiveAutomation = observer(function AutoArchiveAutomation(pro
|
|||
handleClose={() => setmonthModal(false)}
|
||||
handleChange={handleChange}
|
||||
/>
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-100 py-6">
|
||||
<div className="flex flex-col gap-4 border-b border-subtle py-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex items-center justify-center rounded bg-custom-background-90 p-3">
|
||||
<ArchiveRestore className="h-4 w-4 flex-shrink-0 text-custom-text-100" />
|
||||
<div className="flex items-center justify-center rounded-sm bg-layer-3 p-3">
|
||||
<ArchiveRestore className="h-4 w-4 flex-shrink-0 text-primary" />
|
||||
</div>
|
||||
<div className="">
|
||||
<h4 className="text-sm font-medium">{t("project_settings.automations.auto-archive.title")}</h4>
|
||||
<p className="text-sm tracking-tight text-custom-text-200">
|
||||
<h4 className="text-13 font-medium">{t("project_settings.automations.auto-archive.title")}</h4>
|
||||
<p className="text-13 tracking-tight text-tertiary">
|
||||
{t("project_settings.automations.auto-archive.description")}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -100,8 +100,8 @@ export const AutoArchiveAutomation = observer(function AutoArchiveAutomation(pro
|
|||
{currentProjectDetails ? (
|
||||
autoArchiveStatus && (
|
||||
<div className="mx-6">
|
||||
<div className="flex w-full items-center justify-between gap-2 rounded border border-custom-border-200 bg-custom-background-90 px-5 py-4">
|
||||
<div className="w-1/2 text-sm font-medium">
|
||||
<div className="flex w-full items-center justify-between gap-2 rounded-sm border border-subtle bg-surface-2 px-5 py-4">
|
||||
<div className="w-1/2 text-13 font-medium">
|
||||
{t("project_settings.automations.auto-archive.duration")}
|
||||
</div>
|
||||
<div className="w-1/2">
|
||||
|
|
@ -119,13 +119,13 @@ export const AutoArchiveAutomation = observer(function AutoArchiveAutomation(pro
|
|||
<>
|
||||
{PROJECT_AUTOMATION_MONTHS.map((month) => (
|
||||
<CustomSelect.Option key={month.i18n_label} value={month.value}>
|
||||
<span className="text-sm">{t(month.i18n_label, { months: month.value })}</span>
|
||||
<span className="text-13">{t(month.i18n_label, { months: month.value })}</span>
|
||||
</CustomSelect.Option>
|
||||
))}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="flex w-full select-none items-center rounded px-1 py-1.5 text-sm text-custom-text-200 hover:bg-custom-background-80"
|
||||
className="flex w-full select-none items-center rounded-sm px-1 py-1.5 text-13 text-secondary hover:bg-layer-1"
|
||||
onClick={() => setmonthModal(true)}
|
||||
>
|
||||
{t("common.customize_time_range")}
|
||||
|
|
|
|||
|
|
@ -93,12 +93,12 @@ export const AutoCloseAutomation = observer(function AutoCloseAutomation(props:
|
|||
<div className="flex flex-col gap-4 py-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex items-center justify-center rounded bg-custom-background-90 p-3">
|
||||
<div className="flex items-center justify-center rounded-sm bg-layer-3 p-3">
|
||||
<ArchiveX className="h-4 w-4 flex-shrink-0 text-red-500" />
|
||||
</div>
|
||||
<div className="">
|
||||
<h4 className="text-sm font-medium">{t("project_settings.automations.auto-close.title")}</h4>
|
||||
<p className="text-sm tracking-tight text-custom-text-200">
|
||||
<h4 className="text-13 font-medium">{t("project_settings.automations.auto-close.title")}</h4>
|
||||
<p className="text-13 tracking-tight text-tertiary">
|
||||
{t("project_settings.automations.auto-close.description")}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -129,9 +129,9 @@ export const AutoCloseAutomation = observer(function AutoCloseAutomation(props:
|
|||
{currentProjectDetails ? (
|
||||
autoCloseStatus && (
|
||||
<div className="mx-6">
|
||||
<div className="flex flex-col rounded border border-custom-border-200 bg-custom-background-90">
|
||||
<div className="flex flex-col rounded-sm border border-subtle bg-surface-2">
|
||||
<div className="flex w-full items-center justify-between gap-2 px-5 py-4">
|
||||
<div className="w-1/2 text-sm font-medium">
|
||||
<div className="w-1/2 text-13 font-medium">
|
||||
{t("project_settings.automations.auto-close.duration")}
|
||||
</div>
|
||||
<div className="w-1/2">
|
||||
|
|
@ -154,7 +154,7 @@ export const AutoCloseAutomation = observer(function AutoCloseAutomation(props:
|
|||
))}
|
||||
<button
|
||||
type="button"
|
||||
className="flex w-full select-none items-center rounded px-1 py-1.5 text-custom-text-200 hover:bg-custom-background-80"
|
||||
className="flex w-full select-none items-center rounded-sm px-1 py-1.5 text-secondary hover:bg-layer-1"
|
||||
onClick={() => setmonthModal(true)}
|
||||
>
|
||||
{t("common.customize_time_range")}
|
||||
|
|
@ -165,10 +165,10 @@ export const AutoCloseAutomation = observer(function AutoCloseAutomation(props:
|
|||
</div>
|
||||
|
||||
<div className="ppy sm:py-10 flex w-full items-center justify-between gap-2 px-5 py-4">
|
||||
<div className="w-1/2 text-sm font-medium">
|
||||
<div className="w-1/2 text-13 font-medium">
|
||||
{t("project_settings.automations.auto-close.auto_close_status")}
|
||||
</div>
|
||||
<div className="w-1/2 ">
|
||||
<div className="w-1/2">
|
||||
<CustomSearchSelect
|
||||
value={currentProjectDetails?.default_state ?? defaultState}
|
||||
label={
|
||||
|
|
@ -186,11 +186,11 @@ export const AutoCloseAutomation = observer(function AutoCloseAutomation(props:
|
|||
size={EIconSize.LG}
|
||||
/>
|
||||
) : (
|
||||
<StatePropertyIcon className="h-3.5 w-3.5 text-custom-text-200" />
|
||||
<StatePropertyIcon className="h-3.5 w-3.5 text-secondary" />
|
||||
)}
|
||||
{selectedOption?.name
|
||||
? selectedOption.name
|
||||
: (currentDefaultState?.name ?? <span className="text-custom-text-200">{t("state")}</span>)}
|
||||
: (currentDefaultState?.name ?? <span className="text-secondary">{t("state")}</span>)}
|
||||
</div>
|
||||
}
|
||||
onChange={(val: string) => {
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export function SelectMonthModal({ type, initialValues, isOpen, handleClose, han
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
|
||||
<div className="fixed inset-0 bg-backdrop transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-10 overflow-y-auto">
|
||||
|
|
@ -68,10 +68,10 @@ export function SelectMonthModal({ type, initialValues, isOpen, handleClose, han
|
|||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative transform rounded-lg bg-custom-background-100 px-4 pb-4 pt-5 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-full sm:max-w-2xl sm:p-6">
|
||||
<Dialog.Panel className="relative transform rounded-lg bg-surface-1 px-4 pb-4 pt-5 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-full sm:max-w-2xl sm:p-6">
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div>
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-custom-text-100">
|
||||
<Dialog.Title as="h3" className="text-16 font-medium leading-6 text-primary">
|
||||
Customize time range
|
||||
</Dialog.Title>
|
||||
<div className="mt-8 flex items-center gap-2">
|
||||
|
|
@ -97,17 +97,17 @@ export function SelectMonthModal({ type, initialValues, isOpen, handleClose, han
|
|||
ref={ref}
|
||||
hasError={Boolean(errors.close_in)}
|
||||
placeholder="Enter Months"
|
||||
className="w-full border-custom-border-200"
|
||||
className="w-full border-subtle"
|
||||
min={1}
|
||||
max={12}
|
||||
/>
|
||||
<span className="absolute right-8 top-2.5 text-sm text-custom-text-200">Months</span>
|
||||
<span className="absolute right-8 top-2.5 text-13 text-secondary">Months</span>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
|
||||
{errors.close_in && (
|
||||
<span className="px-1 text-sm text-red-500">Select a month between 1 and 12.</span>
|
||||
<span className="px-1 text-13 text-red-500">Select a month between 1 and 12.</span>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
|
|
@ -131,16 +131,16 @@ export function SelectMonthModal({ type, initialValues, isOpen, handleClose, han
|
|||
ref={ref}
|
||||
hasError={Boolean(errors.archive_in)}
|
||||
placeholder="Enter Months"
|
||||
className="w-full border-custom-border-200"
|
||||
className="w-full border-subtle"
|
||||
min={1}
|
||||
max={12}
|
||||
/>
|
||||
<span className="absolute right-8 top-2.5 text-sm text-custom-text-200">Months</span>
|
||||
<span className="absolute right-8 top-2.5 text-13 text-secondary">Months</span>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
{errors.archive_in && (
|
||||
<span className="px-1 text-sm text-red-500">Select a month between 1 and 12.</span>
|
||||
<span className="px-1 text-13 text-red-500">Select a month between 1 and 12.</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
|
@ -148,10 +148,10 @@ export function SelectMonthModal({ type, initialValues, isOpen, handleClose, han
|
|||
</div>
|
||||
</div>
|
||||
<div className="mt-5 flex justify-end gap-2">
|
||||
<Button variant="neutral-primary" size="sm" onClick={onClose}>
|
||||
<Button variant="secondary" size="lg" onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="primary" size="sm" type="submit" loading={isSubmitting}>
|
||||
<Button variant="primary" size="lg" type="submit" loading={isSubmitting}>
|
||||
{isSubmitting ? "Submitting..." : "Submit"}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -96,15 +96,18 @@ export const BaseGanttSidebar = observer(function BaseGanttSidebar<T extends IBa
|
|||
return (
|
||||
<div
|
||||
className={cn("group/list-block", {
|
||||
"rounded bg-custom-background-80": isDragging,
|
||||
"rounded-sm bg-layer-1": isDragging,
|
||||
})}
|
||||
onMouseEnter={() => updateActiveBlockId(blockId)}
|
||||
onMouseLeave={() => updateActiveBlockId(null)}
|
||||
>
|
||||
<Row
|
||||
className={cn("group w-full flex items-center gap-2 pr-4", {
|
||||
"bg-custom-background-90": isBlockHoveredOn,
|
||||
})}
|
||||
className={cn(
|
||||
"group w-full flex items-center gap-2 pr-4 bg-layer-transparent hover:bg-layer-transparent-hover",
|
||||
{
|
||||
"bg-layer-transparent-hover": isBlockHoveredOn,
|
||||
}
|
||||
)}
|
||||
style={{
|
||||
height: `${BLOCK_HEIGHT}px`,
|
||||
}}
|
||||
|
|
@ -112,7 +115,7 @@ export const BaseGanttSidebar = observer(function BaseGanttSidebar<T extends IBa
|
|||
<div className="flex h-full flex-grow items-center justify-between gap-2 truncate">
|
||||
<div className="flex-grow truncate">{renderItem(item)}</div>
|
||||
{duration && (
|
||||
<div className="flex-shrink-0 text-sm text-custom-text-200">
|
||||
<div className="flex-shrink-0 text-13 text-secondary">
|
||||
<span>
|
||||
{duration} day{duration > 1 ? "s" : ""}
|
||||
</span>
|
||||
|
|
@ -129,7 +132,7 @@ export const BaseGanttSidebar = observer(function BaseGanttSidebar<T extends IBa
|
|||
})}
|
||||
{canLoadMoreBlocks && (
|
||||
<div ref={setIntersectionElement} className="p-2">
|
||||
<div className="flex h-10 md:h-8 w-full items-center justify-between gap-1.5 rounded md:px-1 px-4 py-1.5 bg-custom-background-80 animate-pulse" />
|
||||
<div className="flex h-10 md:h-8 w-full items-center justify-between gap-1.5 rounded-sm md:px-1 px-4 py-1.5 bg-layer-1 animate-pulse" />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ export function GroupHeader({ group, itemCount, onToggleGroup }: IGroupHeaderPro
|
|||
return (
|
||||
<button
|
||||
onClick={() => onToggleGroup(group.id)}
|
||||
className="flex w-full items-center gap-2 text-sm font-medium text-custom-text-200"
|
||||
className="flex w-full items-center gap-2 text-13 font-medium text-secondary"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{group.icon}
|
||||
<span>{group.name}</span>
|
||||
</div>
|
||||
<span className="text-xs text-custom-text-300">{itemCount}</span>
|
||||
<span className="text-11 text-tertiary">{itemCount}</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,15 +35,15 @@ export const BaseKanbanGroup = observer(function BaseKanbanGroup<T extends IBase
|
|||
<div
|
||||
ref={groupRef}
|
||||
className={cn(
|
||||
"relative flex flex-shrink-0 flex-col w-[350px] border-[1px] border-transparent p-2 pt-0 max-h-full overflow-y-auto bg-custom-background-90 rounded-md",
|
||||
"relative flex flex-shrink-0 flex-col w-[350px] border-[1px] border-transparent p-2 pt-0 max-h-full overflow-y-auto bg-surface-2 rounded-md",
|
||||
{
|
||||
"bg-custom-background-80": isDraggingOver,
|
||||
"bg-layer-1": isDraggingOver,
|
||||
},
|
||||
groupClassName
|
||||
)}
|
||||
>
|
||||
{/* Group Header */}
|
||||
<div className="sticky top-0 z-[2] w-full flex-shrink-0 bg-custom-background-90 px-1 py-2 cursor-pointer">
|
||||
<div className="sticky top-0 z-[2] w-full flex-shrink-0 bg-surface-2 px-1 py-2 cursor-pointer">
|
||||
{renderGroupHeader ? (
|
||||
renderGroupHeader({ group, itemCount: itemIds.length, isCollapsed, onToggleGroup })
|
||||
) : (
|
||||
|
|
@ -79,7 +79,7 @@ export const BaseKanbanGroup = observer(function BaseKanbanGroup<T extends IBase
|
|||
})}
|
||||
|
||||
{itemIds.length === 0 && (
|
||||
<div className="flex items-center justify-center py-8 text-sm text-custom-text-300">
|
||||
<div className="flex items-center justify-center py-8 text-13 text-tertiary">
|
||||
{t("common.no_items_in_this_group")}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -87,8 +87,8 @@ export const BaseKanbanGroup = observer(function BaseKanbanGroup<T extends IBase
|
|||
)}
|
||||
|
||||
{isDraggingOver && enableDragDrop && (
|
||||
<div className="absolute top-0 left-0 h-full w-full flex items-center justify-center text-sm font-medium text-custom-text-300 rounded bg-custom-background-80/85 border-[1px] border-custom-border-300 z-[2]">
|
||||
<div className="p-3 my-8 flex flex-col rounded items-center text-custom-text-200">
|
||||
<div className="absolute top-0 left-0 h-full w-full flex items-center justify-center text-13 font-medium text-tertiary rounded-sm bg-layer-1/85 border-[1px] border-strong z-[2]">
|
||||
<div className="p-3 my-8 flex flex-col rounded-sm items-center text-secondary">
|
||||
{t("common.drop_here_to_move")}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,23 +21,21 @@ export function LayoutSwitcher(props: Props) {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 rounded bg-custom-background-80 p-1">
|
||||
<div className="flex items-center gap-1 rounded-sm bg-layer-1 p-1">
|
||||
{BASE_LAYOUTS.filter((l) => (layouts ? layouts.includes(l.key) : true)).map((layout) => {
|
||||
const Icon = layout.icon;
|
||||
return (
|
||||
<Tooltip key={layout.key} tooltipContent={layout.label} isMobile={isMobile}>
|
||||
<button
|
||||
type="button"
|
||||
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded transition-all hover:bg-custom-background-100 ${
|
||||
selectedLayout === layout.key ? "bg-custom-background-100 shadow-custom-shadow-2xs" : ""
|
||||
className={`group grid h-[22px] w-7 place-items-center overflow-hidden rounded-sm transition-all hover:bg-surface-1 ${
|
||||
selectedLayout === layout.key ? "bg-surface-1 shadow-custom-shadow-2xs" : ""
|
||||
}`}
|
||||
onClick={() => handleOnChange(layout.key)}
|
||||
>
|
||||
<Icon
|
||||
strokeWidth={2}
|
||||
className={`h-3.5 w-3.5 ${
|
||||
selectedLayout === layout.key ? "text-custom-text-100" : "text-custom-text-200"
|
||||
}`}
|
||||
className={`h-3.5 w-3.5 ${selectedLayout === layout.key ? "text-primary" : "text-secondary"}`}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@ export function GroupHeader({ group, itemCount, onToggleGroup }: IGroupHeaderPro
|
|||
return (
|
||||
<button
|
||||
onClick={() => onToggleGroup(group.id)}
|
||||
className="flex w-full items-center gap-2 py-2 text-sm font-medium text-custom-text-200"
|
||||
className="flex w-full items-center gap-2 py-2 text-13 font-medium text-secondary"
|
||||
>
|
||||
{group.icon}
|
||||
<span>{group.name}</span>
|
||||
<span className="text-xs text-custom-text-300">{itemCount}</span>
|
||||
<span className="text-11 text-tertiary">{itemCount}</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ export const BaseListGroup = observer(function BaseListGroup<T extends IBaseLayo
|
|||
<div
|
||||
ref={groupRef}
|
||||
className={cn("relative flex flex-shrink-0 flex-col border-[1px] border-transparent", {
|
||||
"bg-custom-background-80": isDraggingOver,
|
||||
"bg-layer-1": isDraggingOver,
|
||||
})}
|
||||
>
|
||||
{/* Group Header */}
|
||||
<Row className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 py-1">
|
||||
<Row className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-subtle bg-surface-2 py-1">
|
||||
{renderGroupHeader ? (
|
||||
renderGroupHeader({ group, itemCount: itemIds.length, isCollapsed, onToggleGroup })
|
||||
) : (
|
||||
|
|
@ -76,8 +76,8 @@ export const BaseListGroup = observer(function BaseListGroup<T extends IBaseLayo
|
|||
)}
|
||||
|
||||
{isDraggingOver && enableDragDrop && (
|
||||
<div className="absolute top-0 left-0 h-full w-full flex items-center justify-center text-sm font-medium text-custom-text-300 rounded bg-custom-background-80/85 border-[1px] border-custom-border-300 z-[2]">
|
||||
<div className="p-3 my-8 flex flex-col rounded items-center text-custom-text-200">
|
||||
<div className="absolute top-0 left-0 h-full w-full flex items-center justify-center text-13 font-medium text-tertiary rounded-sm bg-layer-1/85 border-[1px] border-strong z-[2]">
|
||||
<div className="p-3 my-8 flex flex-col rounded-sm items-center text-secondary">
|
||||
{t("common.drop_here_to_move")}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export const BaseListLayout = observer(function BaseListLayout<T extends IBaseLa
|
|||
);
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className={cn("relative size-full overflow-auto bg-custom-background-90", className)}>
|
||||
<div ref={containerRef} className={cn("relative size-full overflow-auto bg-surface-2", className)}>
|
||||
<div className="relative size-full flex flex-col">
|
||||
{groups.map((group) => {
|
||||
const itemIds = groupedItemIds[group.id] || [];
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export const CommentCardDisplay = observer(function CommentCardDisplay(props: Pr
|
|||
|
||||
useEffect(() => {
|
||||
if (!isHashMatch) return;
|
||||
setHighlightClassName("border-custom-primary-100");
|
||||
setHighlightClassName("border-accent-strong");
|
||||
const timeout = setTimeout(() => {
|
||||
setHighlightClassName("");
|
||||
}, 8000);
|
||||
|
|
@ -60,7 +60,7 @@ export const CommentCardDisplay = observer(function CommentCardDisplay(props: Pr
|
|||
return (
|
||||
<div id={commentBlockId} className="relative flex flex-col gap-2">
|
||||
{showAccessSpecifier && (
|
||||
<div className="absolute right-2.5 top-2.5 z-[1] text-custom-text-300">
|
||||
<div className="absolute right-2.5 top-2.5 z-[1] text-tertiary">
|
||||
{comment.access === EIssueCommentAccessSpecifier.INTERNAL ? (
|
||||
<Lock className="size-3" />
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -111,24 +111,24 @@ export const CommentCardEditForm = observer(function CommentCardEditForm(props:
|
|||
type="button"
|
||||
onClick={handleSubmit(onEnter)}
|
||||
disabled={isDisabled}
|
||||
className={`group rounded border border-green-500 bg-green-500/20 p-2 shadow-md duration-300 ${
|
||||
className={`group rounded-sm border border-green-500 bg-green-500/20 p-2 shadow-md duration-300 ${
|
||||
isEmpty ? "cursor-not-allowed bg-gray-200" : "hover:bg-green-500"
|
||||
}`}
|
||||
>
|
||||
<Check
|
||||
className={`h-3 w-3 text-green-500 duration-300 ${isEmpty ? "text-black" : "group-hover:text-white"}`}
|
||||
className={`h-3 w-3 text-green-500 duration-300 ${isEmpty ? "text-black" : "group-hover:text-on-color"}`}
|
||||
/>
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="group rounded border border-red-500 bg-red-500/20 p-2 shadow-md duration-300 hover:bg-red-500"
|
||||
className="group rounded-sm border border-red-500 bg-red-500/20 p-2 shadow-md duration-300 hover:bg-red-500"
|
||||
onClick={() => {
|
||||
setIsEditing(false);
|
||||
editorRef.current?.setEditorValue(comment.comment_html ?? "<p></p>");
|
||||
}}
|
||||
>
|
||||
<CloseIcon className="size-3 text-red-500 duration-300 group-hover:text-white" />
|
||||
<CloseIcon className="size-3 text-red-500 duration-300 group-hover:text-on-color" />
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export const CommentCreate = observer(function CommentCreate(props: TCommentCrea
|
|||
|
||||
return (
|
||||
<div
|
||||
className={cn("sticky bottom-0 z-[4] bg-custom-background-100 sm:static")}
|
||||
className={cn("sticky bottom-0 z-[4] bg-surface-1 sm:static")}
|
||||
onKeyDown={(e) => {
|
||||
if (
|
||||
e.key === "Enter" &&
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export const CommentQuickActions = observer(function CommentQuickActions(props:
|
|||
className={cn(
|
||||
"flex items-center gap-2",
|
||||
{
|
||||
"text-custom-text-400": item.disabled,
|
||||
"text-placeholder": item.disabled,
|
||||
},
|
||||
item.className
|
||||
)}
|
||||
|
|
@ -98,8 +98,8 @@ export const CommentQuickActions = observer(function CommentQuickActions(props:
|
|||
<h5>{item.title}</h5>
|
||||
{item.description && (
|
||||
<p
|
||||
className={cn("text-custom-text-300 whitespace-pre-line", {
|
||||
"text-custom-text-400": item.disabled,
|
||||
className={cn("text-tertiary whitespace-pre-line", {
|
||||
"text-placeholder": item.disabled,
|
||||
})}
|
||||
>
|
||||
{item.description}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export function AccessField(props: Props) {
|
|||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="flex flex-shrink-0 items-stretch gap-0.5 rounded border-[1px] border-custom-border-200 p-1">
|
||||
<div className="flex flex-shrink-0 items-stretch gap-0.5 rounded-sm border-[1px] border-subtle p-1">
|
||||
{accessSpecifiers.map((access, index) => {
|
||||
const label = access.i18n_label ? t(access.i18n_label) : access.label;
|
||||
return (
|
||||
|
|
@ -32,16 +32,13 @@ export function AccessField(props: Props) {
|
|||
type="button"
|
||||
onClick={() => onChange(access.key)}
|
||||
className={cn(
|
||||
"flex-shrink-0 relative flex justify-center items-center w-5 h-5 rounded-sm p-1 transition-all",
|
||||
value === access.key ? "bg-custom-background-80" : "hover:bg-custom-background-80"
|
||||
"flex-shrink-0 relative flex justify-center items-center w-5 h-5 rounded-xs p-1 transition-all",
|
||||
value === access.key ? "bg-layer-1" : "hover:bg-layer-1"
|
||||
)}
|
||||
tabIndex={2 + index}
|
||||
>
|
||||
<access.icon
|
||||
className={cn(
|
||||
"h-3.5 w-3.5 transition-all",
|
||||
value === access.key ? "text-custom-text-100" : "text-custom-text-400"
|
||||
)}
|
||||
className={cn("h-3.5 w-3.5 transition-all", value === access.key ? "text-primary" : "text-placeholder")}
|
||||
strokeWidth={2}
|
||||
/>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
|
|||
import { User } from "./user";
|
||||
|
||||
type TActivityBlockComponent = {
|
||||
icon?: ReactNode;
|
||||
icon?: FC<{ className?: string }>;
|
||||
activity: TWorkspaceBaseActivity;
|
||||
ends: "top" | "bottom" | undefined;
|
||||
children: ReactNode;
|
||||
|
|
@ -20,21 +20,21 @@ type TActivityBlockComponent = {
|
|||
};
|
||||
|
||||
export function ActivityBlockComponent(props: TActivityBlockComponent) {
|
||||
const { icon, activity, ends, children, customUserName } = props;
|
||||
const { icon: Icon, activity, ends, children, customUserName } = props;
|
||||
// hooks
|
||||
const { isMobile } = usePlatformOS();
|
||||
|
||||
if (!activity) return <></>;
|
||||
return (
|
||||
<div
|
||||
className={`relative flex items-start gap-2 text-xs ${
|
||||
className={`relative flex items-start gap-2 text-caption-sm-regular ${
|
||||
ends === "top" ? `pb-3` : ends === "bottom" ? `pt-3` : `py-3`
|
||||
}`}
|
||||
>
|
||||
<div className="flex-shrink-0 ring-6 w-7 h-7 rounded-full overflow-hidden flex justify-center items-start mt-0.5 z-[4] text-custom-text-200">
|
||||
{icon ? icon : <Network className="w-3.5 h-3.5" />}
|
||||
<div className="shrink-0 w-7 h-7 rounded-lg overflow-hidden flex justify-center items-center mt-0.5 z-[4] text-secondary border border-subtle shadow-raised-100">
|
||||
{Icon ? <Icon className="h-3.5 w-3.5 shrink-0" /> : <Network className="h-3.5 w-3.5 shrink-0" />}
|
||||
</div>
|
||||
<div className="w-full text-custom-text-200">
|
||||
<div className="w-full text-secondary">
|
||||
<div className="line-clamp-2">
|
||||
<User activity={activity} customUserName={customUserName} /> {children}
|
||||
</div>
|
||||
|
|
@ -43,7 +43,7 @@ export function ActivityBlockComponent(props: TActivityBlockComponent) {
|
|||
isMobile={isMobile}
|
||||
tooltipContent={`${renderFormattedDate(activity.created_at)}, ${renderFormattedTime(activity.created_at)}`}
|
||||
>
|
||||
<span className="whitespace-nowrap text-custom-text-350 font-medium cursor-help">
|
||||
<span className="whitespace-nowrap text-tertiary font-medium cursor-help">
|
||||
{calculateTimeAgo(activity.created_at)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import type { ReactNode } from "react";
|
||||
import type { FC, ReactNode } from "react";
|
||||
import {
|
||||
RotateCcw,
|
||||
Network,
|
||||
Link as LinkIcon,
|
||||
Calendar,
|
||||
Inbox,
|
||||
AlignLeft,
|
||||
Paperclip,
|
||||
|
|
@ -13,7 +12,6 @@ import {
|
|||
Hash,
|
||||
Clock,
|
||||
Bell,
|
||||
LayoutGrid,
|
||||
GitBranch,
|
||||
Timer,
|
||||
ListTodo,
|
||||
|
|
@ -24,54 +22,55 @@ import {
|
|||
import {
|
||||
ArchiveIcon,
|
||||
CycleIcon,
|
||||
StatePropertyIcon,
|
||||
DueDatePropertyIcon,
|
||||
EstimatePropertyIcon,
|
||||
GridLayoutIcon,
|
||||
IntakeIcon,
|
||||
LabelPropertyIcon,
|
||||
MembersPropertyIcon,
|
||||
ModuleIcon,
|
||||
PriorityPropertyIcon,
|
||||
StartDatePropertyIcon,
|
||||
DueDatePropertyIcon,
|
||||
LabelPropertyIcon,
|
||||
MembersPropertyIcon,
|
||||
EstimatePropertyIcon,
|
||||
StatePropertyIcon,
|
||||
} from "@plane/propel/icons";
|
||||
import { store } from "@/lib/store-context";
|
||||
import type { TProjectActivity } from "@/plane-web/types";
|
||||
|
||||
type ActivityIconMap = {
|
||||
[key: string]: ReactNode;
|
||||
[key: string]: FC<{ className?: string }>;
|
||||
};
|
||||
export const iconsMap: ActivityIconMap = {
|
||||
priority: <PriorityPropertyIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
archived_at: <ArchiveIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
restored: <RotateCcw className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
link: <LinkIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
start_date: <StartDatePropertyIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
target_date: <DueDatePropertyIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
label: <LabelPropertyIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
inbox: <Inbox className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
description: <AlignLeft className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
assignee: <MembersPropertyIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
attachment: <Paperclip className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
name: <Type className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
state: <StatePropertyIcon className="h-4 w-4 flex-shrink-0 text-custom-text-200" />,
|
||||
estimate: <EstimatePropertyIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
cycle: <CycleIcon className="h-4 w-4 flex-shrink-0 text-custom-text-200" />,
|
||||
module: <ModuleIcon className="h-4 w-4 flex-shrink-0 text-custom-text-200" />,
|
||||
page: <FileText className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
network: <Globe className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
identifier: <Hash className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
timezone: <Clock className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
is_project_updates_enabled: <Bell className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
is_epic_enabled: <LayoutGrid className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
is_workflow_enabled: <GitBranch className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
is_time_tracking_enabled: <Timer className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
is_issue_type_enabled: <ListTodo className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
default: <Network className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
module_view: <ModuleIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
cycle_view: <CycleIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
issue_views_view: <Layers className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
page_view: <FileText className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
intake_view: <IntakeIcon className="h-3.5 w-3.5 text-custom-text-200" />,
|
||||
priority: PriorityPropertyIcon,
|
||||
archived_at: ArchiveIcon,
|
||||
restored: RotateCcw,
|
||||
link: LinkIcon,
|
||||
start_date: StartDatePropertyIcon,
|
||||
target_date: DueDatePropertyIcon,
|
||||
label: LabelPropertyIcon,
|
||||
inbox: Inbox,
|
||||
description: AlignLeft,
|
||||
assignee: MembersPropertyIcon,
|
||||
attachment: Paperclip,
|
||||
name: Type,
|
||||
state: StatePropertyIcon,
|
||||
estimate: EstimatePropertyIcon,
|
||||
cycle: CycleIcon,
|
||||
module: ModuleIcon,
|
||||
page: FileText,
|
||||
network: Globe,
|
||||
identifier: Hash,
|
||||
timezone: Clock,
|
||||
is_project_updates_enabled: Bell,
|
||||
is_epic_enabled: GridLayoutIcon,
|
||||
is_workflow_enabled: GitBranch,
|
||||
is_time_tracking_enabled: Timer,
|
||||
is_issue_type_enabled: ListTodo,
|
||||
default: Network,
|
||||
module_view: ModuleIcon,
|
||||
cycle_view: CycleIcon,
|
||||
issue_views_view: Layers,
|
||||
page_view: FileText,
|
||||
intake_view: IntakeIcon,
|
||||
};
|
||||
|
||||
export const messages = (activity: TProjectActivity): { message: string | ReactNode; customUserName?: string } => {
|
||||
|
|
@ -92,7 +91,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
return {
|
||||
message: (
|
||||
<>
|
||||
set the priority to <span className="font-medium text-custom-text-100">{newValue || "none"}</span>
|
||||
set the priority to <span className="font-medium text-primary">{newValue || "none"}</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
|
@ -105,7 +104,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
return {
|
||||
message: (
|
||||
<>
|
||||
renamed the project to <span className="font-medium text-custom-text-100">{newValue}</span>
|
||||
renamed the project to <span className="font-medium text-primary">{newValue}</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
|
@ -119,7 +118,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
<>
|
||||
{newValue ? (
|
||||
<>
|
||||
set the start date to <span className="font-medium text-custom-text-100">{newValue}</span>
|
||||
set the start date to <span className="font-medium text-primary">{newValue}</span>
|
||||
</>
|
||||
) : (
|
||||
"removed the start date"
|
||||
|
|
@ -133,7 +132,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
<>
|
||||
{newValue ? (
|
||||
<>
|
||||
set the target date to <span className="font-medium text-custom-text-100">{newValue}</span>
|
||||
set the target date to <span className="font-medium text-primary">{newValue}</span>
|
||||
</>
|
||||
) : (
|
||||
"removed the target date"
|
||||
|
|
@ -145,7 +144,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
return {
|
||||
message: (
|
||||
<>
|
||||
set the state to <span className="font-medium text-custom-text-100">{newValue || "none"}</span>
|
||||
set the state to <span className="font-medium text-primary">{newValue || "none"}</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
|
@ -155,7 +154,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
<>
|
||||
{newValue ? (
|
||||
<>
|
||||
set the estimate point to <span className="font-medium text-custom-text-100">{newValue}</span>
|
||||
set the estimate point to <span className="font-medium text-primary">{newValue}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
|
@ -163,7 +162,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
{oldValue && (
|
||||
<>
|
||||
{" "}
|
||||
<span className="font-medium text-custom-text-100">{oldValue}</span>
|
||||
<span className="font-medium text-primary">{oldValue}</span>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
|
@ -183,12 +182,12 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
href={`/${workspaceDetail?.slug}/projects/${activity.project}/cycles/${activity.new_identifier}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex font-medium text-custom-text-100"
|
||||
className="inline-flex font-medium text-primary"
|
||||
>
|
||||
{activity.new_value}
|
||||
</a>
|
||||
) : (
|
||||
<span className="font-medium text-custom-text-100">{activity.old_value || "Unknown cycle"}</span>
|
||||
<span className="font-medium text-primary">{activity.old_value || "Unknown cycle"}</span>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
|
|
@ -200,7 +199,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
<span>
|
||||
{verb} this project {verb === "removed" ? "from" : "to"} the module{" "}
|
||||
</span>
|
||||
<span className="font-medium text-custom-text-100">
|
||||
<span className="font-medium text-primary">
|
||||
{verb === "removed" ? oldValue : newValue || "Unknown module"}
|
||||
</span>
|
||||
</>
|
||||
|
|
@ -211,7 +210,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
message: (
|
||||
<>
|
||||
{verb} the label{" "}
|
||||
<span className="font-medium text-custom-text-100">{newValue || oldValue || "Untitled label"}</span>
|
||||
<span className="font-medium text-primary">{newValue || oldValue || "Untitled label"}</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
|
@ -224,7 +223,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
message: (
|
||||
<>
|
||||
{newValue ? "created" : "removed"} the project page{" "}
|
||||
<span className="font-medium text-custom-text-100">{newValue || oldValue || "Untitled page"}</span>
|
||||
<span className="font-medium text-primary">{newValue || oldValue || "Untitled page"}</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
|
@ -236,7 +235,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
return {
|
||||
message: (
|
||||
<>
|
||||
updated project identifier to <span className="font-medium text-custom-text-100">{newValue || "none"}</span>
|
||||
updated project identifier to <span className="font-medium text-primary">{newValue || "none"}</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
|
@ -244,8 +243,7 @@ export const messages = (activity: TProjectActivity): { message: string | ReactN
|
|||
return {
|
||||
message: (
|
||||
<>
|
||||
changed project timezone to{" "}
|
||||
<span className="font-medium text-custom-text-100">{newValue || "default"}</span>
|
||||
changed project timezone to <span className="font-medium text-primary">{newValue || "default"}</span>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ export const User = observer(function User(props: TUser) {
|
|||
return (
|
||||
<>
|
||||
{customUserName || actorDetail?.display_name.includes("-intake") ? (
|
||||
<span className="text-custom-text-100 font-medium">{customUserName || "Plane"}</span>
|
||||
<span className="text-primary font-medium">{customUserName || "Plane"}</span>
|
||||
) : (
|
||||
<Link
|
||||
href={`/${workspaceDetail?.slug}/profile/${actorDetail?.id}`}
|
||||
className="hover:underline text-custom-text-100 font-medium"
|
||||
className="hover:underline text-primary font-medium"
|
||||
>
|
||||
{actorDetail?.display_name}
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ export const AppliedDateFilters = observer(function AppliedDateFilters(props: Pr
|
|||
return (
|
||||
<>
|
||||
{values.map((date) => (
|
||||
<div key={date} className="flex items-center gap-1 rounded bg-custom-background-80 py-1 px-1.5 text-xs">
|
||||
<div key={date} className="flex items-center gap-1 rounded-sm bg-layer-1 py-1 px-1.5 text-11">
|
||||
<span className="normal-case">{getDateLabel(date)}</span>
|
||||
{editable && (
|
||||
<button
|
||||
type="button"
|
||||
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
|
||||
className="grid place-items-center text-tertiary hover:text-secondary"
|
||||
onClick={() => handleRemove(date)}
|
||||
>
|
||||
<CloseIcon height={10} width={10} strokeWidth={2} />
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export const AppliedMembersFilters = observer(function AppliedMembersFilters(pro
|
|||
if (!memberDetails) return null;
|
||||
|
||||
return (
|
||||
<div key={memberId} className="flex items-center gap-1 rounded bg-custom-background-80 py-1 px-1.5 text-xs">
|
||||
<div key={memberId} className="flex items-center gap-1 rounded-sm bg-layer-1 py-1 px-1.5 text-11">
|
||||
<Avatar
|
||||
name={memberDetails.display_name}
|
||||
src={getFileURL(memberDetails.avatar_url)}
|
||||
|
|
@ -39,7 +39,7 @@ export const AppliedMembersFilters = observer(function AppliedMembersFilters(pro
|
|||
{editable && (
|
||||
<button
|
||||
type="button"
|
||||
className="grid place-items-center text-custom-text-300 hover:text-custom-text-200"
|
||||
className="grid place-items-center text-tertiary hover:text-secondary"
|
||||
onClick={() => handleRemove(memberId)}
|
||||
>
|
||||
<CloseIcon height={10} width={10} strokeWidth={2} />
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ type Props = {
|
|||
};
|
||||
|
||||
const IconWrapper = React.memo(function IconWrapper({ icon }: { icon: React.ReactNode }) {
|
||||
return <div className="flex size-4 items-center justify-center overflow-hidden !text-[1rem]">{icon}</div>;
|
||||
return <div className="flex size-4 items-center justify-center overflow-hidden !text-16">{icon}</div>;
|
||||
});
|
||||
|
||||
IconWrapper.displayName = "IconWrapper";
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export function CountChip(props: TCountChip) {
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"relative flex justify-center items-center px-2.5 py-0.5 flex-shrink-0 bg-custom-primary-100/20 text-custom-primary-100 text-xs font-semibold rounded-xl",
|
||||
"relative flex justify-center items-center px-2.5 py-0.5 flex-shrink-0 bg-accent-primary/20 text-accent-primary text-caption-sm-semibold rounded-xl",
|
||||
className
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ export function EmptyState({ title, description, image, primaryButton, secondary
|
|||
<div className={`flex h-full w-full items-center justify-center`}>
|
||||
<div className="flex w-full flex-col items-center text-center">
|
||||
<img src={image} className="w-52 sm:w-60 object-contain" alt={primaryButton?.text || "button image"} />
|
||||
<h6 className="mb-3 mt-6 text-xl font-semibold sm:mt-8">{title}</h6>
|
||||
{description && <p className="mb-7 px-5 text-custom-text-300 sm:mb-8">{description}</p>}
|
||||
<h6 className="mb-3 mt-6 text-18 font-semibold sm:mt-8">{title}</h6>
|
||||
{description && <p className="mb-7 px-5 text-tertiary sm:mb-8">{description}</p>}
|
||||
<div className="flex items-center gap-4">
|
||||
{primaryButton && (
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export const FilterCreatedDate = observer(function FilterCreatedDate(props: Prop
|
|||
<FilterOption isChecked={isCustomDateSelected()} onClick={handleCustomDate} title="Custom" multiple />
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs italic text-custom-text-400">No matches found</p>
|
||||
<p className="text-11 italic text-placeholder">No matches found</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ export const FilterCreatedBy = observer(function FilterCreatedBy(props: Props) {
|
|||
{sortedOptions.length > 5 && (
|
||||
<button
|
||||
type="button"
|
||||
className="ml-8 text-xs font-medium text-custom-primary-100"
|
||||
className="ml-8 text-11 font-medium text-accent-primary"
|
||||
onClick={handleViewToggle}
|
||||
>
|
||||
{itemsToRender === sortedOptions.length ? "View less" : "View all"}
|
||||
|
|
@ -93,7 +93,7 @@ export const FilterCreatedBy = observer(function FilterCreatedBy(props: Props) {
|
|||
)}
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs italic text-custom-text-400">No matches found</p>
|
||||
<p className="text-11 italic text-placeholder">No matches found</p>
|
||||
)
|
||||
) : (
|
||||
<Loader className="space-y-2">
|
||||
|
|
|
|||
|
|
@ -10,18 +10,18 @@ export function LatestFeatureBlock() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="mx-auto mt-16 flex rounded-[3.5px] border border-custom-border-200 bg-custom-background-100 py-2 sm:w-96">
|
||||
<div className="mx-auto mt-16 flex rounded-[3.5px] border border-subtle bg-surface-1 py-2 sm:w-96">
|
||||
<Lightbulb className="mx-3 mr-2 h-7 w-7" />
|
||||
<p className="text-left text-sm text-custom-text-100">
|
||||
<p className="text-left text-13 text-primary">
|
||||
Pages gets a facelift! Write anything and use Galileo to help you start.{" "}
|
||||
<Link href="https://plane.so/changelog" target="_blank" rel="noopener noreferrer">
|
||||
<span className="text-sm font-medium underline hover:cursor-pointer">Learn more</span>
|
||||
<span className="text-13 font-medium underline hover:cursor-pointer">Learn more</span>
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className={`mx-auto mt-8 overflow-hidden rounded-md border border-custom-border-200 object-cover sm:h-52 sm:w-96 ${
|
||||
resolvedTheme === "dark" ? "bg-custom-background-100" : "bg-custom-primary-70"
|
||||
className={`mx-auto mt-8 overflow-hidden rounded-md border border-subtle object-cover sm:h-52 sm:w-96 ${
|
||||
resolvedTheme === "dark" ? "bg-surface-1" : "bg-custom-primary-70"
|
||||
}`}
|
||||
>
|
||||
<div className="h-[90%]">
|
||||
|
|
@ -29,7 +29,7 @@ export function LatestFeatureBlock() {
|
|||
src={latestFeatures}
|
||||
alt="Plane Work items"
|
||||
className={`-mt-2 ml-10 h-full rounded-md ${
|
||||
resolvedTheme === "dark" ? "bg-custom-background-100" : "bg-custom-primary-70"
|
||||
resolvedTheme === "dark" ? "bg-surface-1" : "bg-custom-primary-70"
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
import type { ReactNode } from "react";
|
||||
import { cn } from "@plane/utils";
|
||||
|
||||
type TSidebarPropertyListItemProps = {
|
||||
icon: React.FC<{ className?: string }>;
|
||||
label: string;
|
||||
children: ReactNode;
|
||||
appendElement?: ReactNode;
|
||||
childrenClassName?: string;
|
||||
};
|
||||
|
||||
export function SidebarPropertyListItem(props: TSidebarPropertyListItemProps) {
|
||||
const { icon: Icon, label, children, appendElement, childrenClassName } = props;
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex shrink-0 items-center gap-1 w-30 text-body-xs-regular text-tertiary h-7.5">
|
||||
<Icon className="h-4 w-4 shrink-0" />
|
||||
<span>{label}</span>
|
||||
{appendElement}
|
||||
</div>
|
||||
<div className={cn("grow flex items-center flex-wrap gap-2", childrenClassName)}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -34,9 +34,9 @@ export function NewEmptyState({ title, description, image, primaryButton, disabl
|
|||
return (
|
||||
<div className="flex items-center justify-center overflow-y-auto">
|
||||
<div className=" flex h-full w-full flex-col items-center justify-center ">
|
||||
<div className="m-5 flex max-w-6xl flex-col gap-5 rounded-xl border border-custom-border-200 px-10 py-7 shadow-sm md:m-8">
|
||||
<h3 className="text-2xl font-semibold">{title}</h3>
|
||||
{description && <p className=" text-lg">{description}</p>}
|
||||
<div className="m-5 flex max-w-6xl flex-col gap-5 rounded-xl border border-subtle px-10 py-7 shadow-sm md:m-8">
|
||||
<h3 className="text-20 font-semibold">{title}</h3>
|
||||
{description && <p className=" text-16">{description}</p>}
|
||||
<div className="relative w-full max-w-6xl">
|
||||
<img src={image} className="w-full h-full object-contain" alt={primaryButton?.text || "button image"} />
|
||||
</div>
|
||||
|
|
@ -45,7 +45,7 @@ export function NewEmptyState({ title, description, image, primaryButton, disabl
|
|||
{primaryButton && (
|
||||
<Button
|
||||
className={`relative m-3 max-w-min !px-6 ${comicBox?.direction === "left" ? "flex-row-reverse" : ""}`}
|
||||
size="lg"
|
||||
size="xl"
|
||||
variant="primary"
|
||||
onClick={primaryButton.onClick}
|
||||
disabled={disabled}
|
||||
|
|
@ -73,25 +73,25 @@ export function NewEmptyState({ title, description, image, primaryButton, disabl
|
|||
comicBox?.extraPadding ? "ml-[125px]" : "ml-[90px]"
|
||||
} pb-5`}
|
||||
>
|
||||
<div className="relative mt-5 h-0 w-0 border-b-[11px] border-r-[11px] border-t-[11px] border-custom-border-200 border-y-transparent">
|
||||
<div className="absolute right-[-12px] top-[-10px] h-0 w-0 border-b-[10px] border-r-[10px] border-t-[10px] border-custom-background-100 border-y-transparent" />
|
||||
<div className="relative mt-5 h-0 w-0 border-b-[11px] border-r-[11px] border-t-[11px] border-subtle border-y-transparent">
|
||||
<div className="absolute right-[-12px] top-[-10px] h-0 w-0 border-b-[10px] border-r-[10px] border-t-[10px] border-surface-1 border-y-transparent" />
|
||||
</div>
|
||||
<div className="rounded-md border border-custom-border-200 bg-custom-background-100">
|
||||
<div className="rounded-md border border-subtle bg-surface-1">
|
||||
<h1 className="p-5">
|
||||
<h3 className="text-lg font-semibold">{comicBox?.title}</h3>
|
||||
<h4 className="mt-1 text-sm">{comicBox?.description}</h4>
|
||||
<h3 className="text-16 font-semibold">{comicBox?.title}</h3>
|
||||
<h4 className="mt-1 text-13">{comicBox?.description}</h4>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="absolute right-1/2 top-0 mr-[90px] flex max-w-sm flex-row-reverse pb-5">
|
||||
<div className="relative mt-5 h-0 w-0 border-b-[11px] border-l-[11px] border-t-[11px] border-custom-border-200 border-y-transparent">
|
||||
<div className="absolute left-[-12px] top-[-10px] h-0 w-0 border-b-[10px] border-l-[10px] border-t-[10px] border-custom-background-100 border-y-transparent" />
|
||||
<div className="relative mt-5 h-0 w-0 border-b-[11px] border-l-[11px] border-t-[11px] border-subtle border-y-transparent">
|
||||
<div className="absolute left-[-12px] top-[-10px] h-0 w-0 border-b-[10px] border-l-[10px] border-t-[10px] border-surface-1 border-y-transparent" />
|
||||
</div>
|
||||
<div className="rounded-md border border-custom-border-200 bg-custom-background-100">
|
||||
<div className="rounded-md border border-subtle bg-surface-1">
|
||||
<h1 className="p-5">
|
||||
<h3 className="text-lg font-semibold">{comicBox?.title}</h3>
|
||||
<h4 className="mt-1 text-sm">{comicBox?.description}</h4>
|
||||
<h3 className="text-16 font-semibold">{comicBox?.title}</h3>
|
||||
<h4 className="mt-1 text-13">{comicBox?.description}</h4>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ export function PageAccessIcon(page: TPage) {
|
|||
return (
|
||||
<div>
|
||||
{page.archived_at ? (
|
||||
<ArchiveIcon className="h-2.5 w-2.5 text-custom-text-300" />
|
||||
<ArchiveIcon className="h-2.5 w-2.5 text-tertiary" />
|
||||
) : page.access === EPageAccess.PUBLIC ? (
|
||||
<Earth className="h-2.5 w-2.5 text-custom-text-300" />
|
||||
<Earth className="h-2.5 w-2.5 text-tertiary" />
|
||||
) : (
|
||||
<Lock className="h-2.5 w-2.5 text-custom-text-300" />
|
||||
<Lock className="h-2.5 w-2.5 text-tertiary" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export function SwitcherIcon({ logo_props, logo_url, LabelIcon, size = 12, type
|
|||
<img
|
||||
src={getFileURL(logo_url)}
|
||||
alt="logo"
|
||||
className="rounded-sm object-cover"
|
||||
className="rounded-xs object-cover"
|
||||
style={{ height: size, width: size }}
|
||||
/>
|
||||
);
|
||||
|
|
@ -41,7 +41,7 @@ type TSwitcherLabelProps = {
|
|||
export function SwitcherLabel(props: TSwitcherLabelProps) {
|
||||
const { logo_props, name, LabelIcon, logo_url, type = "lucide" } = props;
|
||||
return (
|
||||
<div className="flex items-center gap-1 text-custom-text-200">
|
||||
<div className="flex items-center gap-1 text-secondary">
|
||||
<SwitcherIcon logo_props={logo_props} logo_url={logo_url} LabelIcon={LabelIcon} type={type} />
|
||||
{truncateText(name ?? "", 40)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -59,13 +59,13 @@ export function IssueLink({ activity }: { activity: IIssueActivity }) {
|
|||
href={workItemLink}
|
||||
target={activity.issue === null ? "_self" : "_blank"}
|
||||
rel={activity.issue === null ? "" : "noopener noreferrer"}
|
||||
className="inline items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
<span className="whitespace-nowrap">{`${activity.project_detail.identifier}-${activity.issue_detail.sequence_id}`}</span>{" "}
|
||||
<span className="font-normal break-all">{activity.issue_detail?.name}</span>
|
||||
<span className="font-regular break-all">{activity.issue_detail?.name}</span>
|
||||
</a>
|
||||
) : (
|
||||
<span className="inline-flex items-center gap-1 font-medium text-custom-text-100 whitespace-nowrap">
|
||||
<span className="inline-flex items-center gap-1 font-medium text-primary whitespace-nowrap">
|
||||
{" a work item"}{" "}
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -84,7 +84,7 @@ function UserLink({ activity }: { activity: IIssueActivity }) {
|
|||
}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center font-medium text-custom-text-100 hover:underline"
|
||||
className="inline-flex items-center font-medium text-primary hover:underline"
|
||||
>
|
||||
{activity.new_value && activity.new_value !== "" ? activity.new_value : activity.old_value}
|
||||
</a>
|
||||
|
|
@ -177,7 +177,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <Users2Icon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <Users2Icon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
archived_at: {
|
||||
message: (activity) => {
|
||||
|
|
@ -194,7 +194,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <ArchiveIcon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <ArchiveIcon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
attachment: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -223,7 +223,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <PaperclipIcon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <PaperclipIcon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
description: {
|
||||
message: (activity, showIssue) => (
|
||||
|
|
@ -237,7 +237,7 @@ const activityDetails: {
|
|||
)}
|
||||
</>
|
||||
),
|
||||
icon: <MessageSquareIcon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <MessageSquareIcon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
estimate_point: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -266,7 +266,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <TriangleIcon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <TriangleIcon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
issue: {
|
||||
message: (activity) => {
|
||||
|
|
@ -289,7 +289,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <WorkItemsIcon width={12} height={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <WorkItemsIcon width={12} height={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
epic: {
|
||||
message: (activity) => {
|
||||
|
|
@ -312,7 +312,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <EpicIcon width={12} height={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <EpicIcon width={12} height={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
labels: {
|
||||
message: (activity, showIssue, workspaceSlug) => {
|
||||
|
|
@ -320,11 +320,9 @@ const activityDetails: {
|
|||
return (
|
||||
<span className="overflow-hidden">
|
||||
added a new label{" "}
|
||||
<span className="inline-flex items-center gap-2 rounded-full border border-custom-border-300 px-2 py-0.5 text-xs">
|
||||
<span className="inline-flex items-center gap-2 rounded-full border border-strong px-2 py-0.5 text-11">
|
||||
<LabelPill labelId={activity.new_identifier ?? ""} workspaceSlug={workspaceSlug} />
|
||||
<span className="flex-shrink font-medium text-custom-text-100 break-all line-clamp-1">
|
||||
{activity.new_value}
|
||||
</span>
|
||||
<span className="flex-shrink font-medium text-primary break-all line-clamp-1">{activity.new_value}</span>
|
||||
</span>
|
||||
{showIssue && (
|
||||
<span className="">
|
||||
|
|
@ -338,11 +336,9 @@ const activityDetails: {
|
|||
return (
|
||||
<>
|
||||
removed the label{" "}
|
||||
<span className="inline-flex items-center gap-2 rounded-full border border-custom-border-300 px-2 py-0.5 text-xs">
|
||||
<span className="inline-flex items-center gap-2 rounded-full border border-strong px-2 py-0.5 text-11">
|
||||
<LabelPill labelId={activity.old_identifier ?? ""} workspaceSlug={workspaceSlug} />
|
||||
<span className="flex-shrink font-medium text-custom-text-100 break-all line-clamp-1">
|
||||
{activity.old_value}
|
||||
</span>
|
||||
<span className="flex-shrink font-medium text-primary break-all line-clamp-1">{activity.old_value}</span>
|
||||
</span>
|
||||
{showIssue && (
|
||||
<span>
|
||||
|
|
@ -353,7 +349,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <TagIcon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <TagIcon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
link: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -365,7 +361,7 @@ const activityDetails: {
|
|||
href={`${activity.new_value}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline-flex items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
link
|
||||
</a>
|
||||
|
|
@ -385,7 +381,7 @@ const activityDetails: {
|
|||
href={`${activity.old_value}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline-flex items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
link
|
||||
</a>
|
||||
|
|
@ -405,7 +401,7 @@ const activityDetails: {
|
|||
href={`${activity.old_value}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline-flex items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
link
|
||||
</a>
|
||||
|
|
@ -418,7 +414,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <Link2Icon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <Link2Icon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
cycles: {
|
||||
message: (activity, showIssue, workspaceSlug) => {
|
||||
|
|
@ -433,7 +429,7 @@ const activityDetails: {
|
|||
href={`/${workspaceSlug}/projects/${activity.project}/cycles/${activity.new_identifier}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
<span className="break-all">{activity.new_value}</span>
|
||||
</a>
|
||||
|
|
@ -447,7 +443,7 @@ const activityDetails: {
|
|||
href={`/${workspaceSlug}/projects/${activity.project}/cycles/${activity.new_identifier}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
<span className="break-all">{activity.new_value}</span>
|
||||
</a>
|
||||
|
|
@ -461,14 +457,14 @@ const activityDetails: {
|
|||
href={`/${workspaceSlug}/projects/${activity.project}/cycles/${activity.old_identifier}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
<span className="break-all">{activity.old_value}</span>
|
||||
</a>
|
||||
</>
|
||||
);
|
||||
},
|
||||
icon: <CycleIcon height={12} width={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <CycleIcon height={12} width={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
modules: {
|
||||
message: (activity, showIssue, workspaceSlug) => {
|
||||
|
|
@ -480,7 +476,7 @@ const activityDetails: {
|
|||
href={`/${workspaceSlug}/projects/${activity.project}/modules/${activity.new_identifier}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
<span className="break-all">{activity.new_value}</span>
|
||||
</a>
|
||||
|
|
@ -494,7 +490,7 @@ const activityDetails: {
|
|||
href={`/${workspaceSlug}/projects/${activity.project}/modules/${activity.new_identifier}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
<span className="break-all">{activity.new_value}</span>
|
||||
</a>
|
||||
|
|
@ -508,14 +504,14 @@ const activityDetails: {
|
|||
href={`/${workspaceSlug}/projects/${activity.project}/modules/${activity.old_identifier}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline items-center gap-1 font-medium text-custom-text-100 hover:underline"
|
||||
className="inline items-center gap-1 font-medium text-primary hover:underline"
|
||||
>
|
||||
<span className="break-all">{activity.old_value}</span>
|
||||
</a>
|
||||
</>
|
||||
);
|
||||
},
|
||||
icon: <ModuleIcon className="h-3 w-3 !text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <ModuleIcon className="h-3 w-3 !text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
name: {
|
||||
message: (activity, showIssue) => (
|
||||
|
|
@ -529,15 +525,14 @@ const activityDetails: {
|
|||
)}
|
||||
</>
|
||||
),
|
||||
icon: <MessageSquareIcon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <MessageSquareIcon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
parent: {
|
||||
message: (activity, showIssue) => {
|
||||
if (!activity.new_value)
|
||||
return (
|
||||
<>
|
||||
removed the parent{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.old_value}</span>
|
||||
removed the parent <span className="font-medium text-primary whitespace-nowrap">{activity.old_value}</span>
|
||||
{showIssue && (
|
||||
<>
|
||||
{" "}
|
||||
|
|
@ -549,8 +544,7 @@ const activityDetails: {
|
|||
else
|
||||
return (
|
||||
<>
|
||||
set the parent to{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.new_value}</span>
|
||||
set the parent to <span className="font-medium text-primary whitespace-nowrap">{activity.new_value}</span>
|
||||
{showIssue && (
|
||||
<>
|
||||
{" "}
|
||||
|
|
@ -560,13 +554,13 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <UsersIcon className="h-3 w-3 !text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <UsersIcon className="h-3 w-3 !text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
priority: {
|
||||
message: (activity, showIssue) => (
|
||||
<>
|
||||
set the priority to{" "}
|
||||
<span className="font-medium text-custom-text-100">
|
||||
<span className="font-medium text-primary">
|
||||
{activity.new_value ? capitalizeFirstLetter(activity.new_value) : "None"}
|
||||
</span>
|
||||
{showIssue && (
|
||||
|
|
@ -577,7 +571,7 @@ const activityDetails: {
|
|||
)}
|
||||
</>
|
||||
),
|
||||
icon: <SignalMediumIcon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <SignalMediumIcon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
relates_to: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -585,18 +579,18 @@ const activityDetails: {
|
|||
return (
|
||||
<>
|
||||
marked that {showIssue ? <IssueLink activity={activity} /> : "this work item"} relates to{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.new_value}</span>.
|
||||
<span className="font-medium text-primary whitespace-nowrap">{activity.new_value}</span>.
|
||||
</>
|
||||
);
|
||||
else
|
||||
return (
|
||||
<>
|
||||
removed the relation from{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.old_value}</span>.
|
||||
<span className="font-medium text-primary whitespace-nowrap">{activity.old_value}</span>.
|
||||
</>
|
||||
);
|
||||
},
|
||||
icon: <RelatedIcon height="12" width="12" className="text-custom-text-200" />,
|
||||
icon: <RelatedIcon height="12" width="12" className="text-secondary" />,
|
||||
},
|
||||
blocking: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -604,18 +598,18 @@ const activityDetails: {
|
|||
return (
|
||||
<>
|
||||
marked {showIssue ? <IssueLink activity={activity} /> : "this work item"} is blocking work item{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.new_value}</span>.
|
||||
<span className="font-medium text-primary whitespace-nowrap">{activity.new_value}</span>.
|
||||
</>
|
||||
);
|
||||
else
|
||||
return (
|
||||
<>
|
||||
removed the blocking work item{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.old_value}</span>.
|
||||
<span className="font-medium text-primary whitespace-nowrap">{activity.old_value}</span>.
|
||||
</>
|
||||
);
|
||||
},
|
||||
icon: <BlockerIcon height="12" width="12" className="text-custom-text-200" />,
|
||||
icon: <BlockerIcon height="12" width="12" className="text-secondary" />,
|
||||
},
|
||||
blocked_by: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -623,18 +617,18 @@ const activityDetails: {
|
|||
return (
|
||||
<>
|
||||
marked {showIssue ? <IssueLink activity={activity} /> : "this work item"} is being blocked by{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.new_value}</span>.
|
||||
<span className="font-medium text-primary whitespace-nowrap">{activity.new_value}</span>.
|
||||
</>
|
||||
);
|
||||
else
|
||||
return (
|
||||
<>
|
||||
removed {showIssue ? <IssueLink activity={activity} /> : "this work item"} being blocked by work item{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.old_value}</span>.
|
||||
<span className="font-medium text-primary whitespace-nowrap">{activity.old_value}</span>.
|
||||
</>
|
||||
);
|
||||
},
|
||||
icon: <BlockedIcon height="12" width="12" className="text-custom-text-200" />,
|
||||
icon: <BlockedIcon height="12" width="12" className="text-secondary" />,
|
||||
},
|
||||
duplicate: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -642,23 +636,23 @@ const activityDetails: {
|
|||
return (
|
||||
<>
|
||||
marked {showIssue ? <IssueLink activity={activity} /> : "this work item"} as duplicate of{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.new_value}</span>.
|
||||
<span className="font-medium text-primary whitespace-nowrap">{activity.new_value}</span>.
|
||||
</>
|
||||
);
|
||||
else
|
||||
return (
|
||||
<>
|
||||
removed {showIssue ? <IssueLink activity={activity} /> : "this work item"} as a duplicate of{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">{activity.old_value}</span>.
|
||||
<span className="font-medium text-primary whitespace-nowrap">{activity.old_value}</span>.
|
||||
</>
|
||||
);
|
||||
},
|
||||
icon: <CopyPlus size={12} className="text-custom-text-200" />,
|
||||
icon: <CopyPlus size={12} className="text-secondary" />,
|
||||
},
|
||||
state: {
|
||||
message: (activity, showIssue) => (
|
||||
<>
|
||||
set the state to <span className="font-medium text-custom-text-100 break-all">{activity.new_value}</span>
|
||||
set the state to <span className="font-medium text-primary break-all">{activity.new_value}</span>
|
||||
{showIssue && (
|
||||
<>
|
||||
{" "}
|
||||
|
|
@ -667,7 +661,7 @@ const activityDetails: {
|
|||
)}
|
||||
</>
|
||||
),
|
||||
icon: <LayoutGridIcon size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <LayoutGridIcon size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
start_date: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -687,7 +681,7 @@ const activityDetails: {
|
|||
return (
|
||||
<>
|
||||
set the start date to{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">
|
||||
<span className="font-medium text-primary whitespace-nowrap">
|
||||
{renderFormattedDate(activity.new_value)}
|
||||
</span>
|
||||
{showIssue && (
|
||||
|
|
@ -699,7 +693,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <Calendar size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <Calendar size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
target_date: {
|
||||
message: (activity, showIssue) => {
|
||||
|
|
@ -719,7 +713,7 @@ const activityDetails: {
|
|||
return (
|
||||
<>
|
||||
set the due date to{" "}
|
||||
<span className="font-medium text-custom-text-100 whitespace-nowrap">
|
||||
<span className="font-medium text-primary whitespace-nowrap">
|
||||
{renderFormattedDate(activity.new_value)}
|
||||
</span>
|
||||
{showIssue && (
|
||||
|
|
@ -730,7 +724,7 @@ const activityDetails: {
|
|||
</>
|
||||
);
|
||||
},
|
||||
icon: <Calendar size={12} className="text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <Calendar size={12} className="text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
inbox: {
|
||||
message: (activity, showIssue) => (
|
||||
|
|
@ -745,7 +739,7 @@ const activityDetails: {
|
|||
{activity.verb === "2" && ` from intake by marking a duplicate work item.`}
|
||||
</>
|
||||
),
|
||||
icon: <IntakeIcon className="size-3 text-custom-text-200" aria-hidden="true" />,
|
||||
icon: <IntakeIcon className="size-3 text-secondary" aria-hidden="true" />,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,7 @@ export const AppHeader = observer(function AppHeader(props: AppHeaderProps) {
|
|||
|
||||
return (
|
||||
<div className={cn("z-[18]", className)}>
|
||||
<Row
|
||||
className={cn(
|
||||
"h-11 flex gap-2 w-full items-center border-b border-custom-border-200 bg-custom-sidebar-background-100",
|
||||
rowClassName
|
||||
)}
|
||||
>
|
||||
<Row className={cn("h-11 flex gap-2 w-full items-center border-b border-subtle bg-surface-1", rowClassName)}>
|
||||
<ExtendedAppHeader header={header} />
|
||||
</Row>
|
||||
{mobileHeader && mobileHeader}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export const ContentOverflowWrapper = observer(function ContentOverflowWrapper(p
|
|||
const {
|
||||
children,
|
||||
maxHeight = 625,
|
||||
buttonClassName = "text-sm font-medium text-custom-primary-100",
|
||||
buttonClassName = "text-13 font-medium text-accent-primary",
|
||||
containerClassName,
|
||||
fallback = null,
|
||||
customButton,
|
||||
|
|
@ -142,7 +142,7 @@ export const ContentOverflowWrapper = observer(function ContentOverflowWrapper(p
|
|||
{customButton || (
|
||||
<button
|
||||
className={cn(
|
||||
"gap-1 w-full text-custom-primary-100 text-sm font-medium transition-opacity duration-300",
|
||||
"gap-1 w-full text-accent-primary text-13 font-medium transition-opacity duration-300",
|
||||
buttonClassName
|
||||
)}
|
||||
onClick={handleToggle}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export const DescriptionVersionsDropdownItem = observer(function DescriptionVers
|
|||
src={getFileURL(versionCreator?.avatar_url ?? "")}
|
||||
/>
|
||||
</span>
|
||||
<p className="text-xs text-custom-text-200 flex items-center gap-1.5">
|
||||
<p className="text-11 text-secondary flex items-center gap-1.5">
|
||||
<span className="font-medium">{versionCreator?.display_name ?? t("common.deactivated_user")}</span>
|
||||
<span>{calculateTimeAgo(version.last_saved_at)}</span>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ export const DescriptionVersionsDropdown = observer(function DescriptionVersions
|
|||
return (
|
||||
<CustomMenu
|
||||
label={
|
||||
<div className="flex items-center gap-1 text-custom-text-300">
|
||||
<div className="flex items-center gap-1 text-tertiary">
|
||||
<span className="flex-shrink-0 size-4 grid place-items-center">
|
||||
<History className="size-3.5" />
|
||||
</span>
|
||||
<p className="text-xs">
|
||||
<p className="text-11">
|
||||
{t("description_versions.last_edited_by")}{" "}
|
||||
<span className="font-medium">{lastUpdatedByUserDisplayName ?? t("common.deactivated_user")}</span>{" "}
|
||||
{calculateTimeAgo(lastUpdatedAt)}
|
||||
|
|
@ -52,7 +52,7 @@ export const DescriptionVersionsDropdown = observer(function DescriptionVersions
|
|||
disabled={disabled}
|
||||
closeOnSelect
|
||||
>
|
||||
<p className="text-xs text-custom-text-300 font-medium mb-1">{t("description_versions.previously_edited_by")}</p>
|
||||
<p className="text-11 text-tertiary font-medium mb-1">{t("description_versions.previously_edited_by")}</p>
|
||||
{versions?.map((version) => (
|
||||
<DescriptionVersionsDropdownItem key={version.id} onClick={onVersionClick} version={version} />
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,19 @@ import { Copy } from "lucide-react";
|
|||
// plane imports
|
||||
import type { EditorRefApi } from "@plane/editor";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { Button, getButtonStyling } from "@plane/propel/button";
|
||||
import { Button } from "@plane/propel/button";
|
||||
import { ChevronLeftIcon, ChevronRightIcon } from "@plane/propel/icons";
|
||||
import { setToast, TOAST_TYPE } from "@plane/propel/toast";
|
||||
import { Tooltip } from "@plane/propel/tooltip";
|
||||
import type { TDescriptionVersion } from "@plane/types";
|
||||
import { Avatar, EModalPosition, EModalWidth, Loader, ModalCore } from "@plane/ui";
|
||||
import { calculateTimeAgo, cn, copyTextToClipboard, getFileURL } from "@plane/utils";
|
||||
import { calculateTimeAgo, cn, getFileURL } from "@plane/utils";
|
||||
// components
|
||||
import { RichTextEditor } from "@/components/editor/rich-text";
|
||||
// hooks
|
||||
import { useMember } from "@/hooks/store/use-member";
|
||||
import { useWorkspace } from "@/hooks/store/use-workspace";
|
||||
import { IconButton } from "@plane/propel/icon-button";
|
||||
|
||||
type Props = {
|
||||
activeVersionDescription: string | undefined;
|
||||
|
|
@ -74,7 +75,7 @@ export const DescriptionVersionsModal = observer(function DescriptionVersionsMod
|
|||
<div className="p-4" data-prevent-outside-click>
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between gap-2 py-0.5">
|
||||
<div className="flex-shrink-0 flex items-center gap-2 text-sm">
|
||||
<div className="flex-shrink-0 flex items-center gap-2 text-13">
|
||||
<p className="flex items-center gap-1">
|
||||
{t("description_versions.edited_by")}
|
||||
<span className="flex-shrink-0">
|
||||
|
|
@ -85,7 +86,7 @@ export const DescriptionVersionsModal = observer(function DescriptionVersionsMod
|
|||
/>
|
||||
</span>
|
||||
</p>
|
||||
<p className="flex-shrink-0 text-custom-text-200">
|
||||
<p className="flex-shrink-0 text-secondary">
|
||||
{calculateTimeAgo(activeVersionDetails?.last_saved_at ?? "")}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -93,13 +94,10 @@ export const DescriptionVersionsModal = observer(function DescriptionVersionsMod
|
|||
<button
|
||||
type="button"
|
||||
onClick={() => handleNavigation("prev")}
|
||||
className={cn(
|
||||
"size-6 text-custom-text-200 grid place-items-center rounded outline-none transition-colors",
|
||||
{
|
||||
"hover:bg-custom-background-80": !isPrevDisabled,
|
||||
"opacity-50": isPrevDisabled,
|
||||
}
|
||||
)}
|
||||
className={cn("size-6 text-secondary grid place-items-center rounded-sm outline-none transition-colors", {
|
||||
"hover:bg-layer-1": !isPrevDisabled,
|
||||
"opacity-50": isPrevDisabled,
|
||||
})}
|
||||
disabled={isPrevDisabled}
|
||||
>
|
||||
<ChevronLeftIcon className="size-4" />
|
||||
|
|
@ -107,13 +105,10 @@ export const DescriptionVersionsModal = observer(function DescriptionVersionsMod
|
|||
<button
|
||||
type="button"
|
||||
onClick={() => handleNavigation("next")}
|
||||
className={cn(
|
||||
"size-6 text-custom-text-200 grid place-items-center rounded outline-none transition-colors",
|
||||
{
|
||||
"hover:bg-custom-background-80": !isNextDisabled,
|
||||
"opacity-50": isNextDisabled,
|
||||
}
|
||||
)}
|
||||
className={cn("size-6 text-secondary grid place-items-center rounded-sm outline-none transition-colors", {
|
||||
"hover:bg-layer-1": !isNextDisabled,
|
||||
"opacity-50": isNextDisabled,
|
||||
})}
|
||||
disabled={isNextDisabled}
|
||||
>
|
||||
<ChevronRightIcon className="size-4" />
|
||||
|
|
@ -155,28 +150,18 @@ export const DescriptionVersionsModal = observer(function DescriptionVersionsMod
|
|||
</div>
|
||||
{/* End version description */}
|
||||
{/* Footer */}
|
||||
<div className="flex items-center justify-between gap-2 pt-4 border-t-[0.5px] border-custom-border-200">
|
||||
<div className="flex items-center justify-between gap-2 pt-4 border-t-[0.5px] border-subtle">
|
||||
<Tooltip tooltipContent={t("common.actions.copy_markdown")}>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"flex-shrink-0",
|
||||
getButtonStyling("neutral-primary", "sm"),
|
||||
"border-none grid place-items-center"
|
||||
)}
|
||||
onClick={handleCopyMarkdown}
|
||||
>
|
||||
<Copy className="size-4" />
|
||||
</button>
|
||||
<IconButton type="button" variant="ghost" size="base" onClick={handleCopyMarkdown} icon={Copy} />
|
||||
</Tooltip>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose} tabIndex={1}>
|
||||
<Button variant="secondary" size="lg" onClick={handleClose} tabIndex={1}>
|
||||
{t("common.cancel")}
|
||||
</Button>
|
||||
{!isRestoreDisabled && (
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
size="lg"
|
||||
onClick={() => {
|
||||
handleRestore(activeVersionDescription ?? "<p></p>");
|
||||
handleClose();
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export function DateFilterModal({ title, handleClose, isOpen, onSelect }: Props)
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
|
||||
<div className="fixed inset-0 bg-backdrop transition-opacity" />
|
||||
</Transition.Child>
|
||||
<div className="fixed inset-0 z-20 flex w-full justify-center overflow-y-auto">
|
||||
<div className="flex min-h-full items-center justify-center p-4 text-center sm:p-0">
|
||||
|
|
@ -73,7 +73,7 @@ export function DateFilterModal({ title, handleClose, isOpen, onSelect }: Props)
|
|||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative flex transform rounded-lg bg-custom-background-100 px-5 py-8 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-full sm:max-w-2xl sm:p-6">
|
||||
<Dialog.Panel className="relative flex transform rounded-lg bg-surface-1 px-5 py-8 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-full sm:max-w-2xl sm:p-6">
|
||||
<form className="space-y-4">
|
||||
<div className="flex w-full justify-between">
|
||||
<Controller
|
||||
|
|
@ -94,7 +94,7 @@ export function DateFilterModal({ title, handleClose, isOpen, onSelect }: Props)
|
|||
const date2Value = getDate(watch("date2"));
|
||||
return (
|
||||
<Calendar
|
||||
className="rounded-md border border-custom-border-200 p-3"
|
||||
className="rounded-md border border-subtle p-3"
|
||||
captionLayout="dropdown"
|
||||
selected={dateValue}
|
||||
defaultMonth={dateValue}
|
||||
|
|
@ -117,7 +117,7 @@ export function DateFilterModal({ title, handleClose, isOpen, onSelect }: Props)
|
|||
const date1Value = getDate(watch("date1"));
|
||||
return (
|
||||
<Calendar
|
||||
className="rounded-md border border-custom-border-200 p-3"
|
||||
className="rounded-md border border-subtle p-3"
|
||||
captionLayout="dropdown"
|
||||
selected={dateValue}
|
||||
defaultMonth={dateValue}
|
||||
|
|
@ -134,20 +134,20 @@ export function DateFilterModal({ title, handleClose, isOpen, onSelect }: Props)
|
|||
)}
|
||||
</div>
|
||||
{watch("filterType") === "range" && (
|
||||
<h6 className="flex items-center gap-1 text-xs">
|
||||
<span className="text-custom-text-200">After:</span>
|
||||
<h6 className="flex items-center gap-1 text-11">
|
||||
<span className="text-secondary">After:</span>
|
||||
<span>{renderFormattedDate(watch("date1"))}</span>
|
||||
<span className="ml-1 text-custom-text-200">Before:</span>
|
||||
<span className="ml-1 text-secondary">Before:</span>
|
||||
{!isInvalid && <span>{renderFormattedDate(watch("date2"))}</span>}
|
||||
</h6>
|
||||
)}
|
||||
<div className="flex justify-end gap-4">
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
<Button variant="secondary" size="lg" onClick={handleClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
size="lg"
|
||||
type="button"
|
||||
onClick={handleSubmit(handleFormSubmit)}
|
||||
disabled={isInvalid}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export function DateFilterSelect({ title, value, onChange }: Props) {
|
|||
<CustomSelect
|
||||
value={value}
|
||||
label={
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<div className="flex items-center gap-2 text-11">
|
||||
{dueDateRange.find((item) => item.value === value)?.icon}
|
||||
<span>
|
||||
{title} {dueDateRange.find((item) => item.value === value)?.name}
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|||
return (
|
||||
<Popover className="relative z-19" ref={ref} tabIndex={tabIndex} onKeyDown={handleKeyDown}>
|
||||
<Popover.Button
|
||||
className="rounded border border-custom-border-300 bg-custom-background-100 px-2 py-1 text-xs text-custom-text-200 hover:text-custom-text-100"
|
||||
className="rounded-sm border border-strong bg-surface-1 px-2 py-1 text-11 text-secondary hover:text-primary"
|
||||
onClick={handleOnClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
|
|
@ -190,21 +190,21 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|||
|
||||
{isOpen && (
|
||||
<Popover.Panel
|
||||
className="absolute right-0 z-20 mt-2 rounded-md border border-custom-border-200 bg-custom-background-100 shadow-custom-shadow-sm"
|
||||
className="absolute right-0 z-20 mt-2 rounded-md border border-subtle bg-surface-1 shadow-custom-shadow-sm"
|
||||
static
|
||||
>
|
||||
<div
|
||||
ref={imagePickerRef}
|
||||
className="flex h-96 w-80 flex-col overflow-auto rounded border border-custom-border-300 bg-custom-background-100 p-3 shadow-2xl md:h-[28rem] md:w-[36rem]"
|
||||
className="flex h-96 w-80 flex-col overflow-auto rounded-sm border border-strong bg-surface-1 p-3 shadow-2xl md:h-[28rem] md:w-[36rem]"
|
||||
>
|
||||
<Tab.Group>
|
||||
<Tab.List as="span" className="inline-block rounded bg-custom-background-80 p-1">
|
||||
<Tab.List as="span" className="inline-block rounded-sm bg-layer-1 p-1">
|
||||
{tabOptions.map((tab) => (
|
||||
<Tab
|
||||
key={tab.key}
|
||||
className={({ selected }) =>
|
||||
`rounded px-4 py-1 text-center text-sm outline-none transition-colors ${
|
||||
selected ? "bg-custom-primary text-white" : "text-custom-text-100"
|
||||
`rounded-sm px-4 py-1 text-center text-13 outline-none transition-colors ${
|
||||
selected ? "bg-accent-primary text-on-color" : "text-primary"
|
||||
}`
|
||||
}
|
||||
>
|
||||
|
|
@ -235,11 +235,11 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|||
onChange={(e) => setFormData({ ...formData, search: e.target.value })}
|
||||
ref={ref}
|
||||
placeholder="Search for images"
|
||||
className="w-full text-sm"
|
||||
className="w-full text-13"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Button variant="primary" onClick={() => setSearchParams(formData.search)} size="sm">
|
||||
<Button variant="primary" onClick={() => setSearchParams(formData.search)}>
|
||||
Search
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -258,13 +258,13 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|||
<img
|
||||
src={image.urls.small}
|
||||
alt={image.alt_description}
|
||||
className="absolute left-0 top-0 h-full w-full cursor-pointer rounded object-cover"
|
||||
className="absolute left-0 top-0 h-full w-full cursor-pointer rounded-sm object-cover"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="pt-7 text-center text-xs text-custom-text-300">No images found.</p>
|
||||
<p className="pt-7 text-center text-11 text-secondary">No images found.</p>
|
||||
)
|
||||
) : (
|
||||
<Loader className="grid grid-cols-4 gap-4">
|
||||
|
|
@ -292,7 +292,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|||
<img
|
||||
src={imageUrl}
|
||||
alt={`Cover image ${index + 1}`}
|
||||
className="absolute left-0 top-0 h-full w-full cursor-pointer rounded object-cover hover:opacity-80 transition-opacity"
|
||||
className="absolute left-0 top-0 h-full w-full cursor-pointer rounded-sm object-cover hover:opacity-80 transition-opacity"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
|
@ -305,13 +305,13 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|||
{...getRootProps()}
|
||||
className={`relative grid h-full w-full cursor-pointer place-items-center rounded-lg p-12 text-center focus:outline-none focus:ring-2 focus:ring-custom-primary focus:ring-offset-2 ${
|
||||
(image === null && isDragActive) || !value
|
||||
? "border-2 border-dashed border-custom-border-200 hover:bg-custom-background-90"
|
||||
? "border-2 border-dashed border-subtle hover:bg-surface-2"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="absolute right-0 top-0 z-40 -translate-y-1/2 rounded bg-custom-background-90 px-2 py-0.5 text-xs font-medium text-custom-text-200"
|
||||
className="absolute right-0 top-0 z-40 -translate-y-1/2 rounded-sm bg-surface-2 px-2 py-0.5 text-11 font-medium text-secondary"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
|
|
@ -325,7 +325,7 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|||
</>
|
||||
) : (
|
||||
<div>
|
||||
<span className="mt-2 block text-sm font-medium text-custom-text-200">
|
||||
<span className="mt-2 block text-13 font-medium text-secondary">
|
||||
{isDragActive ? "Drop image here to upload" : "Drag & drop image here"}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -335,18 +335,18 @@ export const ImagePickerPopover = observer(function ImagePickerPopover(props: Pr
|
|||
</div>
|
||||
</div>
|
||||
{fileRejections.length > 0 && (
|
||||
<p className="text-sm text-red-500">
|
||||
<p className="text-13 text-red-500">
|
||||
{fileRejections[0].errors[0].code === "file-too-large"
|
||||
? "The image size cannot exceed 5 MB."
|
||||
: "Please upload a file in a valid format."}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<p className="text-sm text-custom-text-200">File formats supported- .jpeg, .jpg, .png, .webp</p>
|
||||
<p className="text-13 text-secondary">File formats supported- .jpeg, .jpg, .png, .webp</p>
|
||||
|
||||
<div className="flex h-12 items-start justify-end gap-2">
|
||||
<Button
|
||||
variant="neutral-primary"
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
setIsOpen(false);
|
||||
setImage(null);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { FC } from "react";
|
||||
import React from "react";
|
||||
// ui
|
||||
import { Tooltip } from "@plane/propel/tooltip";
|
||||
|
|
@ -64,7 +63,7 @@ export function ListItem(props: IListItemProps) {
|
|||
<div ref={parentRef} className="relative">
|
||||
<Row
|
||||
className={cn(
|
||||
"group min-h-[52px] flex w-full flex-col items-center justify-between gap-3 py-4 text-sm border-b border-custom-border-200 bg-custom-background-100 hover:bg-custom-background-90 ",
|
||||
"group min-h-[52px] flex w-full flex-col items-center justify-between gap-3 py-4 text-13 border-b border-subtle bg-layer-transparent hover:bg-layer-transparent-hover",
|
||||
{ "xl:gap-5 xl:py-0 xl:flex-row": isSidebarOpen, "lg:gap-5 lg:py-0 lg:flex-row": !isSidebarOpen },
|
||||
className
|
||||
)}
|
||||
|
|
@ -82,7 +81,7 @@ export function ListItem(props: IListItemProps) {
|
|||
<div className={cn("flex items-center gap-4 truncate", leftElementClassName)}>
|
||||
{prependTitleElement && <span className="flex items-center flex-shrink-0">{prependTitleElement}</span>}
|
||||
<Tooltip tooltipContent={title} position="top" isMobile={isMobile}>
|
||||
<span className="truncate text-sm">{title}</span>
|
||||
<span className="truncate text-13">{title}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{appendTitleElement && (
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export const BulkDeleteIssuesModalItem = observer(function BulkDeleteIssuesModal
|
|||
value={issue.id}
|
||||
className={({ active }) =>
|
||||
`flex cursor-pointer select-none items-center justify-between rounded-md px-3 py-2 my-0.5 ${
|
||||
active ? "bg-custom-background-80 text-custom-text-100" : ""
|
||||
active ? "bg-layer-1 text-primary" : ""
|
||||
}`
|
||||
}
|
||||
>
|
||||
|
|
@ -39,7 +39,7 @@ export const BulkDeleteIssuesModalItem = observer(function BulkDeleteIssuesModal
|
|||
issueTypeId={issue.type_id}
|
||||
projectIdentifier={issue.project__identifier}
|
||||
issueSequenceId={issue.sequence_id}
|
||||
textContainerClassName="text-xs"
|
||||
size="xs"
|
||||
/>
|
||||
<span>{issue.name}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -127,9 +127,9 @@ export const BulkDeleteIssuesModal = observer(function BulkDeleteIssuesModal(pro
|
|||
issues.length > 0 ? (
|
||||
<li className="p-2">
|
||||
{query === "" && (
|
||||
<h2 className="mb-2 mt-4 px-3 text-xs font-semibold text-custom-text-100">Select work items to delete</h2>
|
||||
<h2 className="mb-2 mt-4 px-3 text-11 font-semibold text-primary">Select work items to delete</h2>
|
||||
)}
|
||||
<ul className="text-sm text-custom-text-200">
|
||||
<ul className="text-13 text-secondary">
|
||||
{issues.map((issue) => (
|
||||
<BulkDeleteIssuesModalItem
|
||||
issue={issue}
|
||||
|
|
@ -152,7 +152,7 @@ export const BulkDeleteIssuesModal = observer(function BulkDeleteIssuesModal(pro
|
|||
return (
|
||||
<Transition.Root show={isOpen} as={React.Fragment} afterLeave={() => setQuery("")} appear>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
<div className="fixed inset-0 z-20 overflow-y-auto bg-custom-backdrop p-4 transition-opacity sm:p-6 md:p-20">
|
||||
<div className="fixed inset-0 z-20 overflow-y-auto bg-backdrop p-4 transition-opacity sm:p-6 md:p-20">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="ease-out duration-300"
|
||||
|
|
@ -163,7 +163,7 @@ export const BulkDeleteIssuesModal = observer(function BulkDeleteIssuesModal(pro
|
|||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative flex w-full items-center justify-center ">
|
||||
<div className="w-full max-w-2xl transform divide-y divide-custom-border-200 divide-opacity-10 rounded-lg bg-custom-background-100 shadow-custom-shadow-md transition-all">
|
||||
<div className="w-full max-w-2xl transform divide-y divide-subtle-1 divide-opacity-10 rounded-lg bg-surface-1 shadow-custom-shadow-md transition-all">
|
||||
<form>
|
||||
<Combobox
|
||||
onChange={(val: string) => {
|
||||
|
|
@ -178,21 +178,18 @@ export const BulkDeleteIssuesModal = observer(function BulkDeleteIssuesModal(pro
|
|||
>
|
||||
<div className="relative m-1">
|
||||
<Search
|
||||
className="pointer-events-none absolute left-4 top-3.5 h-5 w-5 text-custom-text-100 text-opacity-40"
|
||||
className="pointer-events-none absolute left-4 top-3.5 h-5 w-5 text-primary text-opacity-40"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
className="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-custom-text-100 outline-none focus:ring-0 sm:text-sm"
|
||||
className="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-primary outline-none focus:ring-0 sm:text-13"
|
||||
placeholder="Search..."
|
||||
onChange={(event) => setQuery(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Combobox.Options
|
||||
static
|
||||
className="max-h-80 scroll-py-2 divide-y divide-custom-border-200 overflow-y-auto"
|
||||
>
|
||||
<Combobox.Options static className="max-h-80 scroll-py-2 divide-y divide-subtle-1 overflow-y-auto">
|
||||
{isSearching ? (
|
||||
<Loader className="space-y-3 p-3">
|
||||
<Loader.Item height="40px" />
|
||||
|
|
@ -208,10 +205,15 @@ export const BulkDeleteIssuesModal = observer(function BulkDeleteIssuesModal(pro
|
|||
|
||||
{issues.length > 0 && (
|
||||
<div className="flex items-center justify-end gap-2 p-3">
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
<Button variant="secondary" size="lg" onClick={handleClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="danger" size="sm" onClick={handleSubmit(handleDelete)} loading={isSubmitting}>
|
||||
<Button
|
||||
variant="error-fill"
|
||||
size="lg"
|
||||
onClick={handleSubmit(handleDelete)}
|
||||
loading={isSubmitting}
|
||||
>
|
||||
{isSubmitting ? "Deleting..." : "Delete selected work items"}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ export const ChangeEmailModal = observer(function ChangeEmailModal(props: Props)
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 transition-opacity bg-custom-backdrop" />
|
||||
<div className="fixed inset-0 transition-opacity bg-backdrop" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="overflow-y-auto fixed inset-0 z-30">
|
||||
|
|
@ -152,17 +152,17 @@ export const ChangeEmailModal = observer(function ChangeEmailModal(props: Props)
|
|||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-custom-background-100 px-4 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-[30rem]">
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-surface-1 px-4 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-[30rem]">
|
||||
<div className="py-4 space-y-0">
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-custom-text-100">
|
||||
<Dialog.Title as="h3" className="text-16 font-medium leading-6 text-primary">
|
||||
{changeEmailT("title")}
|
||||
</Dialog.Title>
|
||||
<p className="my-4 text-sm text-custom-text-200">{changeEmailT("description")}</p>
|
||||
<p className="my-4 text-13 text-secondary">{changeEmailT("description")}</p>
|
||||
</div>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4" noValidate>
|
||||
<div className="flex flex-col gap-1">
|
||||
{secondStep && (
|
||||
<h4 className="text-sm font-medium text-custom-text-200">{changeEmailT("form.email.label")}</h4>
|
||||
<h4 className="text-13 font-medium text-secondary">{changeEmailT("form.email.label")}</h4>
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
|
|
@ -186,18 +186,18 @@ export const ChangeEmailModal = observer(function ChangeEmailModal(props: Props)
|
|||
placeholder={changeEmailT("form.email.placeholder")}
|
||||
className={cn(
|
||||
{ "border-red-500": errors.email },
|
||||
{ "cursor-not-allowed !bg-custom-background-90": secondStep }
|
||||
{ "cursor-not-allowed !bg-surface-2": secondStep }
|
||||
)}
|
||||
disabled={secondStep}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{errors?.email && <span className="text-xs text-red-500">{errors?.email?.message}</span>}
|
||||
{errors?.email && <span className="text-11 text-red-500">{errors?.email?.message}</span>}
|
||||
</div>
|
||||
|
||||
{secondStep && (
|
||||
<div className="flex flex-col gap-1">
|
||||
<h4 className="text-sm font-medium text-custom-text-200">{changeEmailT("form.code.label")}</h4>
|
||||
<h4 className="text-13 font-medium text-secondary">{changeEmailT("form.code.label")}</h4>
|
||||
<Controller
|
||||
control={control}
|
||||
name="code"
|
||||
|
|
@ -216,17 +216,17 @@ export const ChangeEmailModal = observer(function ChangeEmailModal(props: Props)
|
|||
)}
|
||||
/>
|
||||
{errors?.code ? (
|
||||
<span className="text-xs text-red-500">{errors?.code?.message}</span>
|
||||
<span className="text-11 text-red-500">{errors?.code?.message}</span>
|
||||
) : (
|
||||
<span className="text-xs text-green-700">{changeEmailT("form.code.helper_text")}</span>
|
||||
<span className="text-11 text-green-700">{changeEmailT("form.code.helper_text")}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-custom-border-200 py-4">
|
||||
<Button type="button" variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
<div className="flex items-center justify-end gap-2 border-t-[0.5px] border-subtle py-4">
|
||||
<Button type="button" variant="secondary" size="lg" onClick={handleClose}>
|
||||
{changeEmailT("actions.cancel")}
|
||||
</Button>
|
||||
<Button type="submit" variant="primary" size="sm" disabled={isSubmitting}>
|
||||
<Button type="submit" variant="primary" size="lg" disabled={isSubmitting}>
|
||||
{isSubmitting
|
||||
? changeEmailT("states.sending")
|
||||
: secondStep
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
|
||||
<div className="fixed inset-0 bg-backdrop transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-30 overflow-y-auto p-4 sm:p-6 md:p-20">
|
||||
|
|
@ -156,7 +156,7 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
leaveFrom="opacity-100 scale-100"
|
||||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative mx-auto max-w-2xl transform rounded-lg bg-custom-background-100 shadow-custom-shadow-md transition-all">
|
||||
<Dialog.Panel className="relative mx-auto max-w-2xl transform rounded-lg bg-surface-1 shadow-custom-shadow-md transition-all">
|
||||
<Combobox
|
||||
as="div"
|
||||
onChange={(val: ISearchIssueResponse) => {
|
||||
|
|
@ -167,11 +167,11 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
>
|
||||
<div className="relative m-1">
|
||||
<Search
|
||||
className="pointer-events-none absolute left-4 top-3.5 h-5 w-5 text-custom-text-100 text-opacity-40"
|
||||
className="pointer-events-none absolute left-4 top-3.5 h-5 w-5 text-primary text-opacity-40"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<Combobox.Input
|
||||
className="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-sm text-custom-text-100 outline-none placeholder:text-custom-text-400 focus:ring-0"
|
||||
className="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-13 text-primary outline-none placeholder:text-placeholder focus:ring-0"
|
||||
placeholder={t("common.search.placeholder")}
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
|
|
@ -179,41 +179,42 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col-reverse gap-4 p-2 text-[0.825rem] text-custom-text-200 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="flex flex-col-reverse gap-4 p-2 text-13 text-secondary sm:flex-row sm:items-center sm:justify-between">
|
||||
{selectedIssues.length > 0 ? (
|
||||
<div className="mt-1 flex flex-wrap items-center gap-2">
|
||||
{selectedIssues.map((issue) => (
|
||||
<div
|
||||
key={issue.id}
|
||||
className="flex items-center gap-1 whitespace-nowrap rounded-md border border-custom-border-200 bg-custom-background-80 py-1 pl-2 text-xs text-custom-text-100"
|
||||
className="flex items-center gap-1 whitespace-nowrap rounded-md border border-subtle bg-layer-1 py-1 pl-2 text-11 text-primary"
|
||||
>
|
||||
<IssueIdentifier
|
||||
projectId={issue.project_id}
|
||||
issueTypeId={issue.type_id}
|
||||
projectIdentifier={issue.project__identifier}
|
||||
issueSequenceId={issue.sequence_id}
|
||||
textContainerClassName="text-xs text-custom-text-200"
|
||||
size="xs"
|
||||
variant="secondary"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="group p-1"
|
||||
onClick={() => setSelectedIssues((prevData) => prevData.filter((i) => i.id !== issue.id))}
|
||||
>
|
||||
<CloseIcon className="h-3 w-3 text-custom-text-200 group-hover:text-custom-text-100" />
|
||||
<CloseIcon className="h-3 w-3 text-secondary group-hover:text-primary" />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="w-min whitespace-nowrap rounded-md border border-custom-border-200 bg-custom-background-80 p-2 text-xs">
|
||||
<div className="w-min whitespace-nowrap rounded-md border border-subtle bg-layer-1 p-2 text-11">
|
||||
{t("issue.select.empty")}
|
||||
</div>
|
||||
)}
|
||||
{workspaceLevelToggle && (
|
||||
<Tooltip tooltipContent="Toggle workspace level search" isMobile={isMobile}>
|
||||
<div
|
||||
className={`flex flex-shrink-0 cursor-pointer items-center gap-1 text-xs ${
|
||||
isWorkspaceLevel ? "text-custom-text-100" : "text-custom-text-200"
|
||||
className={`flex flex-shrink-0 cursor-pointer items-center gap-1 text-11 ${
|
||||
isWorkspaceLevel ? "text-primary" : "text-secondary"
|
||||
}`}
|
||||
>
|
||||
<ToggleSwitch
|
||||
|
|
@ -238,9 +239,9 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
>
|
||||
{/* TODO: Translate here */}
|
||||
{searchTerm !== "" && (
|
||||
<h5 className="mx-2 text-[0.825rem] text-custom-text-200">
|
||||
<h5 className="mx-2 text-13 text-secondary">
|
||||
Search results for{" "}
|
||||
<span className="text-custom-text-100">
|
||||
<span className="text-primary">
|
||||
{'"'}
|
||||
{searchTerm}
|
||||
{'"'}
|
||||
|
|
@ -266,7 +267,7 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
searchTerm={searchTerm}
|
||||
/>
|
||||
) : (
|
||||
<ul className={`text-sm text-custom-text-100 ${filteredIssues.length > 0 ? "p-2" : ""}`}>
|
||||
<ul className={`text-13 text-primary ${filteredIssues.length > 0 ? "p-2" : ""}`}>
|
||||
{filteredIssues.map((issue) => {
|
||||
const selected = selectedIssues.some((i) => i.id === issue.id);
|
||||
|
||||
|
|
@ -277,9 +278,9 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
htmlFor={`issue-${issue.id}`}
|
||||
value={issue}
|
||||
className={({ active }) =>
|
||||
`group flex w-full cursor-pointer select-none items-center justify-between gap-2 rounded-md px-3 py-2 my-0.5 text-custom-text-200 ${
|
||||
active ? "bg-custom-background-80 text-custom-text-100" : ""
|
||||
} ${selected ? "text-custom-text-100" : ""}`
|
||||
`group flex w-full cursor-pointer select-none items-center justify-between gap-2 rounded-md px-3 py-2 my-0.5 text-secondary ${
|
||||
active ? "bg-layer-1 text-primary" : ""
|
||||
} ${selected ? "text-primary" : ""}`
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-2 truncate">
|
||||
|
|
@ -296,7 +297,8 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
issueTypeId={issue.type_id}
|
||||
projectIdentifier={issue.project__identifier}
|
||||
issueSequenceId={issue.sequence_id}
|
||||
textContainerClassName="text-xs text-custom-text-200"
|
||||
size="xs"
|
||||
variant="secondary"
|
||||
/>
|
||||
</span>
|
||||
<span className="truncate">{issue.name}</span>
|
||||
|
|
@ -310,7 +312,7 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
sequenceId: issue?.sequence_id,
|
||||
})}
|
||||
target="_blank"
|
||||
className="z-1 relative hidden flex-shrink-0 text-custom-text-200 hover:text-custom-text-100 group-hover:block"
|
||||
className="z-1 relative hidden flex-shrink-0 text-secondary hover:text-primary group-hover:block"
|
||||
rel="noopener noreferrer"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
|
|
@ -327,8 +329,7 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
</Combobox>
|
||||
<div className="flex justify-between items-center p-3">
|
||||
<Button
|
||||
variant="link-primary"
|
||||
size="sm"
|
||||
variant="link"
|
||||
onClick={handleSelectIssues}
|
||||
disabled={filteredIssues.length === 0}
|
||||
className={filteredIssues.length === 0 ? "p-0" : ""}
|
||||
|
|
@ -338,12 +339,12 @@ export function ExistingIssuesListModal(props: Props) {
|
|||
: t("issue.select.select_all")}
|
||||
</Button>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
<Button variant="secondary" size="lg" onClick={handleClose}>
|
||||
{t("common.cancel")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
size="lg"
|
||||
onClick={onSubmit}
|
||||
loading={isSubmitting}
|
||||
disabled={isSubmitting || selectedIssues.length === 0}
|
||||
|
|
|
|||
|
|
@ -208,14 +208,14 @@ export function GptAssistantPopover(props: Props) {
|
|||
>
|
||||
<Popover.Panel
|
||||
as="div"
|
||||
className={`fixed z-10 flex w-full min-w-[50rem] max-w-full flex-col space-y-4 overflow-hidden rounded-[10px] border border-custom-border-200 bg-custom-background-100 p-4 shadow ${className}`}
|
||||
className={`fixed z-10 flex w-full min-w-[50rem] max-w-full flex-col space-y-4 overflow-hidden rounded-[10px] border border-subtle bg-surface-1 p-4 shadow ${className}`}
|
||||
ref={setPopperElement as Ref<HTMLDivElement>}
|
||||
style={styles.popper}
|
||||
{...attributes.popper}
|
||||
>
|
||||
<div className="vertical-scroll-enable max-h-72 space-y-4 overflow-y-auto">
|
||||
{prompt && (
|
||||
<div className="text-sm">
|
||||
<div className="text-13">
|
||||
Content:
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
|
|
@ -230,7 +230,7 @@ export function GptAssistantPopover(props: Props) {
|
|||
</div>
|
||||
)}
|
||||
{response !== "" && (
|
||||
<div className="page-block-section max-h-[8rem] text-sm">
|
||||
<div className="page-block-section max-h-[8rem] text-13">
|
||||
Response:
|
||||
<RichTextEditor
|
||||
editable={false}
|
||||
|
|
@ -244,7 +244,7 @@ export function GptAssistantPopover(props: Props) {
|
|||
</div>
|
||||
)}
|
||||
{invalidResponse && (
|
||||
<div className="text-sm text-red-500">
|
||||
<div className="text-13 text-red-500">
|
||||
No response could be generated. This may be due to insufficient content or task information. Please try
|
||||
again.
|
||||
</div>
|
||||
|
|
@ -274,17 +274,17 @@ export function GptAssistantPopover(props: Props) {
|
|||
<>{responseActionButton}</>
|
||||
) : (
|
||||
<>
|
||||
<div className="flex items-start justify-center gap-2 text-sm text-custom-primary">
|
||||
<div className="flex items-start justify-center gap-2 text-13 text-custom-primary">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<p>By using this feature, you consent to sharing the message with a 3rd party service. </p>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="neutral-primary" size="sm" onClick={onClose}>
|
||||
<Button variant="secondary" onClick={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
<Button variant="primary" size="sm" onClick={handleSubmit(handleAIResponse)} loading={isSubmitting}>
|
||||
<Button variant="primary" onClick={handleSubmit(handleAIResponse)} loading={isSubmitting}>
|
||||
{generateResponseButtonText}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
|
||||
<div className="fixed inset-0 bg-backdrop transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-30 overflow-y-auto">
|
||||
|
|
@ -113,9 +113,9 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props
|
|||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-custom-background-100 px-5 py-8 text-left shadow-custom-shadow-md transition-all sm:w-full sm:max-w-xl sm:p-6">
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-surface-1 px-5 py-8 text-left shadow-custom-shadow-md transition-all sm:w-full sm:max-w-xl sm:p-6">
|
||||
<div className="space-y-5">
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-custom-text-100">
|
||||
<Dialog.Title as="h3" className="text-16 font-medium leading-6 text-primary">
|
||||
Upload Image
|
||||
</Dialog.Title>
|
||||
<div className="space-y-3">
|
||||
|
|
@ -124,7 +124,7 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props
|
|||
{...getRootProps()}
|
||||
className={`relative grid h-80 w-80 cursor-pointer place-items-center rounded-lg p-12 text-center focus:outline-none focus:ring-2 focus:ring-custom-primary focus:ring-offset-2 ${
|
||||
(image === null && isDragActive) || !value
|
||||
? "border-2 border-dashed border-custom-border-200 hover:bg-custom-background-90"
|
||||
? "border-2 border-dashed border-subtle hover:bg-surface-2"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
|
|
@ -132,7 +132,7 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props
|
|||
<>
|
||||
<button
|
||||
type="button"
|
||||
className="absolute right-0 top-0 z-40 -translate-y-1/2 translate-x-1/2 rounded bg-custom-background-90 px-2 py-0.5 text-xs font-medium text-custom-text-200"
|
||||
className="absolute right-0 top-0 z-40 -translate-y-1/2 translate-x-1/2 rounded-sm bg-surface-2 px-2 py-0.5 text-11 font-medium text-secondary"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
|
|
@ -144,8 +144,8 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props
|
|||
</>
|
||||
) : (
|
||||
<div>
|
||||
<UserCirclePropertyIcon className="mx-auto h-16 w-16 text-custom-text-200" />
|
||||
<span className="mt-2 block text-sm font-medium text-custom-text-200">
|
||||
<UserCirclePropertyIcon className="mx-auto h-16 w-16 text-secondary" />
|
||||
<span className="mt-2 block text-13 font-medium text-secondary">
|
||||
{isDragActive ? "Drop image here to upload" : "Drag & drop image here"}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -155,7 +155,7 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props
|
|||
</div>
|
||||
</div>
|
||||
{fileRejections.length > 0 && (
|
||||
<p className="text-sm text-red-500">
|
||||
<p className="text-13 text-red-500">
|
||||
{fileRejections[0].errors[0].code === "file-too-large"
|
||||
? "The image size cannot exceed 5 MB."
|
||||
: "Please upload a file in a valid format."}
|
||||
|
|
@ -163,18 +163,18 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<p className="my-4 text-sm text-custom-text-200">File formats supported- .jpeg, .jpg, .png, .webp</p>
|
||||
<p className="my-4 text-13 text-secondary">File formats supported- .jpeg, .jpg, .png, .webp</p>
|
||||
<div className="flex items-center justify-between">
|
||||
<Button variant="danger" size="sm" onClick={handleImageRemove} disabled={!value}>
|
||||
<Button variant="error-fill" size="lg" onClick={handleImageRemove} disabled={!value}>
|
||||
{isRemoving ? "Removing" : "Remove"}
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
<Button variant="secondary" size="lg" onClick={handleClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
size="lg"
|
||||
onClick={handleSubmit}
|
||||
disabled={!image}
|
||||
loading={isImageUploading}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM
|
|||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
|
||||
<div className="fixed inset-0 bg-backdrop transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-30 overflow-y-auto">
|
||||
|
|
@ -126,9 +126,9 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM
|
|||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-custom-background-100 px-5 py-8 text-left shadow-custom-shadow-md transition-all sm:w-full sm:max-w-xl sm:p-6">
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-surface-1 px-5 py-8 text-left shadow-custom-shadow-md transition-all sm:w-full sm:max-w-xl sm:p-6">
|
||||
<div className="space-y-5">
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-custom-text-100">
|
||||
<Dialog.Title as="h3" className="text-16 font-medium leading-6 text-primary">
|
||||
Upload image
|
||||
</Dialog.Title>
|
||||
<div className="space-y-3">
|
||||
|
|
@ -137,7 +137,7 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM
|
|||
{...getRootProps()}
|
||||
className={`relative grid h-80 w-80 cursor-pointer place-items-center rounded-lg p-12 text-center focus:outline-none focus:ring-2 focus:ring-custom-primary focus:ring-offset-2 ${
|
||||
(image === null && isDragActive) || !value
|
||||
? "border-2 border-dashed border-custom-border-200 hover:bg-custom-background-90"
|
||||
? "border-2 border-dashed border-subtle hover:bg-surface-2"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
|
|
@ -145,7 +145,7 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM
|
|||
<>
|
||||
<button
|
||||
type="button"
|
||||
className="absolute right-0 top-0 z-40 -translate-y-1/2 translate-x-1/2 rounded bg-custom-background-90 px-2 py-0.5 text-xs font-medium text-custom-text-200"
|
||||
className="absolute right-0 top-0 z-40 -translate-y-1/2 translate-x-1/2 rounded-sm bg-surface-2 px-2 py-0.5 text-11 font-medium text-secondary"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
|
|
@ -157,8 +157,8 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM
|
|||
</>
|
||||
) : (
|
||||
<div>
|
||||
<UserCirclePropertyIcon className="mx-auto h-16 w-16 text-custom-text-200" />
|
||||
<span className="mt-2 block text-sm font-medium text-custom-text-200">
|
||||
<UserCirclePropertyIcon className="mx-auto h-16 w-16 text-secondary" />
|
||||
<span className="mt-2 block text-13 font-medium text-secondary">
|
||||
{isDragActive ? "Drop image here to upload" : "Drag & drop image here"}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -168,7 +168,7 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM
|
|||
</div>
|
||||
</div>
|
||||
{fileRejections.length > 0 && (
|
||||
<p className="text-sm text-red-500">
|
||||
<p className="text-13 text-red-500">
|
||||
{fileRejections[0].errors[0].code === "file-too-large"
|
||||
? "The image size cannot exceed 5 MB."
|
||||
: "Please upload a file in a valid format."}
|
||||
|
|
@ -176,18 +176,24 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<p className="my-4 text-sm text-custom-text-200">File formats supported- .jpeg, .jpg, .png, .webp</p>
|
||||
<p className="my-4 text-13 text-secondary">File formats supported- .jpeg, .jpg, .png, .webp</p>
|
||||
<div className="flex items-center justify-between">
|
||||
<Button variant="danger" size="sm" onClick={handleImageRemove} disabled={!value} loading={isRemoving}>
|
||||
<Button
|
||||
variant="error-fill"
|
||||
size="lg"
|
||||
onClick={handleImageRemove}
|
||||
disabled={!value}
|
||||
loading={isRemoving}
|
||||
>
|
||||
{isRemoving ? "Removing" : "Remove"}
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="neutral-primary" size="sm" onClick={handleClose}>
|
||||
<Button variant="secondary" size="lg" onClick={handleClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
size="lg"
|
||||
onClick={handleSubmit}
|
||||
disabled={!image}
|
||||
loading={isImageUploading}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ function RenderIfVisible(props: Props) {
|
|||
|
||||
const child = isVisible ? <>{children}</> : placeholderChildren;
|
||||
const style = isVisible || !shouldRecordHeights ? {} : { height: placeholderHeight.current, width: "100%" };
|
||||
const className = isVisible || placeholderChildren ? classNames : cn(classNames, "bg-custom-background-80");
|
||||
const className = isVisible || placeholderChildren ? classNames : cn(classNames, "bg-layer-1");
|
||||
|
||||
return React.createElement(as, { ref: intersectionRef, style, className }, child);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export const AssigneeStatComponent = observer(function AssigneeStatComponent(pro
|
|||
key={`unassigned-${index}`}
|
||||
title={
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-4 w-4 rounded-full border-2 border-custom-border-200 bg-custom-background-80">
|
||||
<div className="h-4 w-4 rounded-full border-2 border-subtle bg-layer-1">
|
||||
<img src={userImage} className="rounded-full w-full h-full object-cover" alt="User" />
|
||||
</div>
|
||||
<span>{t("no_assignee")}</span>
|
||||
|
|
@ -68,10 +68,10 @@ export const AssigneeStatComponent = observer(function AssigneeStatComponent(pro
|
|||
})
|
||||
) : (
|
||||
<div className="flex h-full flex-col items-center justify-center gap-2">
|
||||
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-custom-background-80">
|
||||
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-layer-1">
|
||||
<img src={emptyMembers} className="h-12 w-12 object-contain" alt="empty members" />
|
||||
</div>
|
||||
<h6 className="text-base text-custom-text-300">{t("no_assignee")}</h6>
|
||||
<h6 className="text-14 text-tertiary">{t("no_assignee")}</h6>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export const LabelStatComponent = observer(function LabelStatComponent(props: TL
|
|||
backgroundColor: label.color ?? "transparent",
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-ellipsis truncate">{label.title ?? t("no_labels_yet")}</span>
|
||||
<span className="text-11 text-ellipsis truncate">{label.title ?? t("no_labels_yet")}</span>
|
||||
</div>
|
||||
}
|
||||
completed={label.completed}
|
||||
|
|
@ -63,7 +63,7 @@ export const LabelStatComponent = observer(function LabelStatComponent(props: TL
|
|||
backgroundColor: label.color ?? "transparent",
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs">{label.title ?? t("no_labels_yet")}</span>
|
||||
<span className="text-11">{label.title ?? t("no_labels_yet")}</span>
|
||||
</div>
|
||||
}
|
||||
completed={label.completed}
|
||||
|
|
@ -74,10 +74,10 @@ export const LabelStatComponent = observer(function LabelStatComponent(props: TL
|
|||
})
|
||||
) : (
|
||||
<div className="flex h-full flex-col items-center justify-center gap-2">
|
||||
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-custom-background-80">
|
||||
<div className="flex h-20 w-20 items-center justify-center rounded-full bg-layer-1">
|
||||
<img src={emptyLabel} className="h-12 w-12 object-contain" alt="empty label" />
|
||||
</div>
|
||||
<h6 className="text-base text-custom-text-300">{t("no_labels_yet")}</h6>
|
||||
<h6 className="text-14 text-tertiary">{t("no_labels_yet")}</h6>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export const StateGroupStatComponent = observer(function StateGroupStatComponent
|
|||
title={
|
||||
<div className="flex items-center gap-2">
|
||||
<StateGroupIcon stateGroup={group.state as TStateGroups} />
|
||||
<span className="text-xs capitalize">{group.state}</span>
|
||||
<span className="text-11 capitalize">{group.state}</span>
|
||||
</div>
|
||||
}
|
||||
completed={group.completed}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ export const SidebarHamburgerToggle = observer(function SidebarHamburgerToggle()
|
|||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="group flex-shrink-0 size-7 grid place-items-center rounded hover:bg-custom-background-80 transition-all bg-custom-background-90"
|
||||
className="group flex-shrink-0 size-7 grid place-items-center rounded-sm hover:bg-layer-1 transition-all bg-surface-2"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<PanelRight className="size-3.5 text-custom-text-200 transition-all group-hover:text-custom-text-100" />
|
||||
<PanelRight className="size-3.5 text-secondary transition-all group-hover:text-primary" />
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ type TSingleProgressStatsProps = {
|
|||
export function SingleProgressStats({ title, completed, total, onClick, selected = false }: TSingleProgressStatsProps) {
|
||||
return (
|
||||
<div
|
||||
className={`flex w-full items-center justify-between gap-4 rounded-sm p-1 text-xs ${
|
||||
onClick ? "cursor-pointer hover:bg-custom-background-90" : ""
|
||||
} ${selected ? "bg-custom-background-80" : ""}`}
|
||||
className={`flex w-full items-center justify-between gap-4 rounded-xs p-1 text-11 ${
|
||||
onClick ? "cursor-pointer hover:bg-surface-2" : ""
|
||||
} ${selected ? "bg-layer-1" : ""}`}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="w-4/6">{title}</div>
|
||||
|
|
|
|||
|
|
@ -88,19 +88,17 @@ export function ColorPickerInput(props: Props) {
|
|||
<>
|
||||
<Popover.Button
|
||||
type="button"
|
||||
className={`group inline-flex items-center outline-none ${
|
||||
open ? "text-custom-text-100" : "text-custom-text-200"
|
||||
}`}
|
||||
className={`group inline-flex items-center outline-none ${open ? "text-primary" : "text-secondary"}`}
|
||||
>
|
||||
{watch(name) && watch(name) !== "" ? (
|
||||
<span
|
||||
className="h-4 w-4 rounded border border-custom-border-200"
|
||||
className="h-4 w-4 rounded-sm border border-subtle"
|
||||
style={{
|
||||
backgroundColor: `${watch(name)}`,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Palette className="h-3.5 w-3.5 text-custom-text-100" />
|
||||
<Palette className="h-3.5 w-3.5 text-primary" />
|
||||
)}
|
||||
</Popover.Button>
|
||||
|
||||
|
|
|
|||
|
|
@ -127,11 +127,11 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
return (
|
||||
<form onSubmit={handleSubmit(handleUpdateTheme)}>
|
||||
<div className="space-y-5">
|
||||
<h3 className="text-lg font-semibold text-custom-text-100">{t("customize_your_theme")}</h3>
|
||||
<h3 className="text-16 font-semibold text-primary">{t("customize_your_theme")}</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="grid grid-cols-1 gap-x-8 gap-y-4 sm:grid-cols-2 md:grid-cols-3">
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("background_color")}</h3>
|
||||
<h3 className="text-left text-13 font-medium text-secondary">{t("background_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
|
|
@ -143,7 +143,7 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
value={value}
|
||||
onChange={(val) => handleValueChange(val, onChange)}
|
||||
placeholder="#0d101b"
|
||||
className="w-full placeholder:text-custom-text-400/60"
|
||||
className="w-full placeholder:text-placeholder/60"
|
||||
style={{
|
||||
backgroundColor: watch("background"),
|
||||
color: watch("text"),
|
||||
|
|
@ -152,12 +152,12 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
{errors.background && <p className="mt-1 text-xs text-red-500">{errors.background.message}</p>}
|
||||
{errors.background && <p className="mt-1 text-11 text-red-500">{errors.background.message}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("text_color")}</h3>
|
||||
<h3 className="text-left text-13 font-medium text-secondary">{t("text_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
|
|
@ -169,7 +169,7 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
value={value}
|
||||
onChange={(val) => handleValueChange(val, onChange)}
|
||||
placeholder="#c5c5c5"
|
||||
className="w-full placeholder:text-custom-text-400/60"
|
||||
className="w-full placeholder:text-placeholder/60"
|
||||
style={{
|
||||
backgroundColor: watch("text"),
|
||||
color: watch("background"),
|
||||
|
|
@ -178,12 +178,12 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
{errors.text && <p className="mt-1 text-xs text-red-500">{errors.text.message}</p>}
|
||||
{errors.text && <p className="mt-1 text-11 text-red-500">{errors.text.message}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("primary_color")}</h3>
|
||||
<h3 className="text-left text-13 font-medium text-secondary">{t("primary_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
|
|
@ -195,7 +195,7 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
value={value}
|
||||
onChange={(val) => handleValueChange(val, onChange)}
|
||||
placeholder="#3f76ff"
|
||||
className="w-full placeholder:text-custom-text-400/60"
|
||||
className="w-full placeholder:text-placeholder/60"
|
||||
style={{
|
||||
backgroundColor: watch("primary"),
|
||||
color: watch("text"),
|
||||
|
|
@ -204,12 +204,12 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
{errors.primary && <p className="mt-1 text-xs text-red-500">{errors.primary.message}</p>}
|
||||
{errors.primary && <p className="mt-1 text-11 text-red-500">{errors.primary.message}</p>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("sidebar_background_color")}</h3>
|
||||
<h3 className="text-left text-13 font-medium text-secondary">{t("sidebar_background_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
|
|
@ -221,7 +221,7 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
value={value}
|
||||
onChange={(val) => handleValueChange(val, onChange)}
|
||||
placeholder="#0d101b"
|
||||
className="w-full placeholder:text-custom-text-400/60"
|
||||
className="w-full placeholder:text-placeholder/60"
|
||||
style={{
|
||||
backgroundColor: watch("sidebarBackground"),
|
||||
color: watch("sidebarText"),
|
||||
|
|
@ -231,13 +231,13 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
)}
|
||||
/>
|
||||
{errors.sidebarBackground && (
|
||||
<p className="mt-1 text-xs text-red-500">{errors.sidebarBackground.message}</p>
|
||||
<p className="mt-1 text-11 text-red-500">{errors.sidebarBackground.message}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
<h3 className="text-left text-sm font-medium text-custom-text-200">{t("sidebar_text_color")}</h3>
|
||||
<h3 className="text-left text-13 font-medium text-secondary">{t("sidebar_text_color")}</h3>
|
||||
<div className="w-full">
|
||||
<Controller
|
||||
control={control}
|
||||
|
|
@ -249,7 +249,7 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
value={value}
|
||||
onChange={(val) => handleValueChange(val, onChange)}
|
||||
placeholder="#c5c5c5"
|
||||
className="w-full placeholder:text-custom-text-400/60"
|
||||
className="w-full placeholder:text-placeholder/60"
|
||||
style={{
|
||||
backgroundColor: watch("sidebarText"),
|
||||
color: watch("sidebarBackground"),
|
||||
|
|
@ -258,7 +258,7 @@ export const CustomThemeSelector = observer(function CustomThemeSelector(props:
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
{errors.sidebarText && <p className="mt-1 text-xs text-red-500">{errors.sidebarText.message}</p>}
|
||||
{errors.sidebarText && <p className="mt-1 text-11 text-red-500">{errors.sidebarText.message}</p>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export function ThemeSwitch(props: Props) {
|
|||
value ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<div
|
||||
className="border-1 relative flex h-4 w-4 rotate-45 transform items-center justify-center rounded-full border"
|
||||
className="border-1 relative flex h-4 w-4 rotate-45 transform items-center justify-center rounded-full"
|
||||
style={{
|
||||
borderColor: value.icon.border,
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
);
|
||||
|
||||
return cycleId ? (
|
||||
<div className="flex flex-col gap-4 p-4 min-h-[17rem] overflow-hidden bg-custom-background-100 col-span-1 lg:col-span-2 xl:col-span-1 border border-custom-border-200 rounded-lg">
|
||||
<div className="flex flex-col gap-4 p-4 min-h-[17rem] overflow-hidden bg-surface-1 col-span-1 lg:col-span-2 xl:col-span-1 border border-subtle rounded-lg">
|
||||
<Tab.Group
|
||||
as={Fragment}
|
||||
defaultIndex={currentValue(tab)}
|
||||
|
|
@ -120,7 +120,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
>
|
||||
<Tab.List
|
||||
as="div"
|
||||
className="relative border-[0.5px] border-custom-border-200 rounded bg-custom-background-80 p-[1px] grid"
|
||||
className="relative border-[0.5px] border-subtle rounded-sm bg-layer-1 p-[1px] grid"
|
||||
style={{
|
||||
gridTemplateColumns: `repeat(3, 1fr)`,
|
||||
}}
|
||||
|
|
@ -128,10 +128,10 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
<Tab
|
||||
className={({ selected }) =>
|
||||
cn(
|
||||
"relative z-[1] font-semibold text-xs rounded-[3px] py-1.5 text-custom-text-400 focus:outline-none transition duration-500",
|
||||
"relative z-[1] font-semibold text-11 rounded-[3px] py-1.5 text-placeholder focus:outline-none transition duration-500",
|
||||
{
|
||||
"text-custom-text-300 bg-custom-background-100": selected,
|
||||
"hover:text-custom-text-300": !selected,
|
||||
"text-tertiary bg-surface-1": selected,
|
||||
"hover:text-tertiary": !selected,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -141,10 +141,10 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
<Tab
|
||||
className={({ selected }) =>
|
||||
cn(
|
||||
"relative z-[1] font-semibold text-xs rounded-[3px] py-1.5 text-custom-text-400 focus:outline-none transition duration-500",
|
||||
"relative z-[1] font-semibold text-11 rounded-[3px] py-1.5 text-placeholder focus:outline-none transition duration-500",
|
||||
{
|
||||
"text-custom-text-300 bg-custom-background-100": selected,
|
||||
"hover:text-custom-text-300": !selected,
|
||||
"text-tertiary bg-surface-1": selected,
|
||||
"hover:text-tertiary": !selected,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -154,10 +154,10 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
<Tab
|
||||
className={({ selected }) =>
|
||||
cn(
|
||||
"relative z-[1] font-semibold text-xs rounded-[3px] py-1.5 text-custom-text-400 focus:outline-none transition duration-500",
|
||||
"relative z-[1] font-semibold text-11 rounded-[3px] py-1.5 text-placeholder focus:outline-none transition duration-500",
|
||||
{
|
||||
"text-custom-text-300 bg-custom-background-100": selected,
|
||||
"hover:text-custom-text-300": !selected,
|
||||
"text-tertiary bg-surface-1": selected,
|
||||
"hover:text-tertiary": !selected,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -169,7 +169,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
<Tab.Panels as={Fragment}>
|
||||
<Tab.Panel
|
||||
as="div"
|
||||
className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-custom-text-200 vertical-scrollbar scrollbar-sm"
|
||||
className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-secondary vertical-scrollbar scrollbar-sm"
|
||||
>
|
||||
<div
|
||||
ref={issuesContainerRef}
|
||||
|
|
@ -186,7 +186,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
return (
|
||||
<div
|
||||
key={issue.id}
|
||||
className="group flex cursor-pointer items-center justify-between gap-2 rounded-md hover:bg-custom-background-90 p-1"
|
||||
className="group flex cursor-pointer items-center justify-between gap-2 rounded-md hover:bg-surface-2 p-1"
|
||||
onClick={() => {
|
||||
if (issue.id) {
|
||||
setPeekIssue({
|
||||
|
|
@ -202,13 +202,9 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
}}
|
||||
>
|
||||
<div className="flex items-center gap-1.5 flex-grow w-full min-w-24 truncate">
|
||||
<IssueIdentifier
|
||||
issueId={issue.id}
|
||||
projectId={projectId}
|
||||
textContainerClassName="text-xs text-custom-text-200"
|
||||
/>
|
||||
<IssueIdentifier issueId={issue.id} projectId={projectId} size="xs" variant="secondary" />
|
||||
<Tooltip position="top-start" tooltipHeading="Title" tooltipContent={issue.name}>
|
||||
<span className="text-[0.825rem] text-custom-text-100 truncate">{issue.name}</span>
|
||||
<span className="text-13 text-primary truncate">{issue.name}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<PriorityIcon priority={issue.priority} withContainer size={12} />
|
||||
|
|
@ -227,9 +223,9 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
tooltipHeading="Target Date"
|
||||
tooltipContent={renderFormattedDate(issue.target_date)}
|
||||
>
|
||||
<div className="h-full flex truncate items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80 group-hover:bg-custom-background-100 cursor-pointer">
|
||||
<div className="h-full flex truncate items-center gap-1.5 rounded-sm text-11 px-2 py-0.5 bg-layer-1 group-hover:bg-surface-1 cursor-pointer">
|
||||
<CalendarCheck className="h-3 w-3 flex-shrink-0" />
|
||||
<span className="text-xs truncate">
|
||||
<span className="text-11 truncate">
|
||||
{renderFormattedDateWithoutYear(issue.target_date)}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -243,7 +239,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
<div
|
||||
ref={setIssueLoaderElement}
|
||||
className={
|
||||
"h-11 relative flex items-center gap-3 bg-custom-background-80 p-3 text-sm cursor-pointer animate-pulse"
|
||||
"h-11 relative flex items-center gap-3 bg-layer-1 p-3 text-13 cursor-pointer animate-pulse"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -264,7 +260,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
|
||||
<Tab.Panel
|
||||
as="div"
|
||||
className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-custom-text-200 vertical-scrollbar scrollbar-sm"
|
||||
className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-secondary vertical-scrollbar scrollbar-sm"
|
||||
>
|
||||
{cycle && !isEmpty(cycle.distribution) ? (
|
||||
cycle?.distribution?.assignees && cycle.distribution.assignees.length > 0 ? (
|
||||
|
|
@ -300,7 +296,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
key={`unassigned-${index}`}
|
||||
title={
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-5 w-5 rounded-full border-2 border-custom-border-200 bg-custom-background-80">
|
||||
<div className="h-5 w-5 rounded-full border-2 border-subtle bg-layer-1">
|
||||
<img src={userImage} height="100%" width="100%" className="rounded-full" alt="User" />
|
||||
</div>
|
||||
<span>{t("no_assignee")}</span>
|
||||
|
|
@ -326,7 +322,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
|
||||
<Tab.Panel
|
||||
as="div"
|
||||
className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-custom-text-200 vertical-scrollbar scrollbar-sm"
|
||||
className="flex h-52 w-full flex-col gap-1 overflow-y-auto text-secondary vertical-scrollbar scrollbar-sm"
|
||||
>
|
||||
{cycle && !isEmpty(cycle.distribution) ? (
|
||||
cycle?.distribution?.labels && cycle.distribution.labels.length > 0 ? (
|
||||
|
|
@ -341,7 +337,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
backgroundColor: label.color ?? "#000000",
|
||||
}}
|
||||
/>
|
||||
<span className="text-xs text-ellipsis truncate">{label.label_name ?? "No labels"}</span>
|
||||
<span className="text-11 text-ellipsis truncate">{label.label_name ?? "No labels"}</span>
|
||||
</div>
|
||||
}
|
||||
completed={label.completed_issues}
|
||||
|
|
@ -370,7 +366,7 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active
|
|||
</Tab.Group>
|
||||
</div>
|
||||
) : (
|
||||
<Loader className="flex flex-col gap-4 min-h-[17rem] overflow-hidden bg-custom-background-100 col-span-1 lg:col-span-2 xl:col-span-1">
|
||||
<Loader className="flex flex-col gap-4 min-h-[17rem] overflow-hidden bg-surface-1 col-span-1 lg:col-span-2 xl:col-span-1">
|
||||
<Loader.Item width="100%" height="17rem" />
|
||||
</Loader>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -45,12 +45,10 @@ export const ActiveCycleProductivity = observer(function ActiveCycleProductivity
|
|||
const completionChartDistributionData = chartDistributionData?.completion_chart || undefined;
|
||||
|
||||
return cycle && completionChartDistributionData ? (
|
||||
<div className="flex flex-col min-h-[17rem] gap-5 px-3.5 py-4 bg-custom-background-100 border border-custom-border-200 rounded-lg">
|
||||
<div className="flex flex-col min-h-[17rem] gap-5 px-3.5 py-4 bg-surface-1 border border-subtle rounded-lg">
|
||||
<div className="relative flex items-center justify-between gap-4">
|
||||
<Link href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycle?.id}`}>
|
||||
<h3 className="text-base text-custom-text-300 font-semibold">
|
||||
{t("project_cycles.active_cycle.issue_burndown")}
|
||||
</h3>
|
||||
<h3 className="text-14 text-tertiary font-semibold">{t("project_cycles.active_cycle.issue_burndown")}</h3>
|
||||
</Link>
|
||||
<EstimateTypeDropdown value={estimateType} onChange={onChange} cycleId={cycle.id} projectId={projectId} />
|
||||
</div>
|
||||
|
|
@ -59,7 +57,7 @@ export const ActiveCycleProductivity = observer(function ActiveCycleProductivity
|
|||
{cycle.total_issues > 0 ? (
|
||||
<>
|
||||
<div className="h-full w-full px-2">
|
||||
<div className="flex items-center justify-end gap-4 py-1 text-xs text-custom-text-300">
|
||||
<div className="flex items-center justify-end gap-4 py-1 text-11 text-tertiary">
|
||||
{estimateType === "points" ? (
|
||||
<span>{`Pending points - ${cycle.backlog_estimate_points + cycle.unstarted_estimate_points + cycle.started_estimate_points}`}</span>
|
||||
) : (
|
||||
|
|
@ -98,7 +96,7 @@ export const ActiveCycleProductivity = observer(function ActiveCycleProductivity
|
|||
</Link>
|
||||
</div>
|
||||
) : (
|
||||
<Loader className="flex flex-col min-h-[17rem] gap-5 bg-custom-background-100 border border-custom-border-200 rounded-lg">
|
||||
<Loader className="flex flex-col min-h-[17rem] gap-5 bg-surface-1 border border-subtle rounded-lg">
|
||||
<Loader.Item width="100%" height="100%" />
|
||||
</Loader>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ export const ActiveCycleProgress = observer(function ActiveCycleProgress(props:
|
|||
const resolvedPath = resolvedTheme === "light" ? lightProgressAsset : darkProgressAsset;
|
||||
|
||||
return cycle && cycle.hasOwnProperty("started_issues") ? (
|
||||
<div className="flex flex-col min-h-[17rem] gap-5 py-4 px-3.5 bg-custom-background-100 border border-custom-border-200 rounded-lg">
|
||||
<div className="flex flex-col min-h-[17rem] gap-5 py-4 px-3.5 bg-surface-1 border border-subtle rounded-lg">
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<h3 className="text-base text-custom-text-300 font-semibold">{t("project_cycles.active_cycle.progress")}</h3>
|
||||
<h3 className="text-14 text-tertiary font-semibold">{t("project_cycles.active_cycle.progress")}</h3>
|
||||
{cycle.total_issues > 0 && (
|
||||
<span className="flex gap-1 text-sm text-custom-text-400 font-medium whitespace-nowrap rounded-sm px-3 py-1 ">
|
||||
<span className="flex gap-1 text-13 text-placeholder font-medium whitespace-nowrap rounded-xs px-3 py-1 ">
|
||||
{`${cycle.completed_issues + cycle.cancelled_issues}/${cycle.total_issues - cycle.cancelled_issues} ${
|
||||
cycle.completed_issues + cycle.cancelled_issues > 1 ? "Work items" : "Work item"
|
||||
} closed`}
|
||||
|
|
@ -66,7 +66,7 @@ export const ActiveCycleProgress = observer(function ActiveCycleProgress(props:
|
|||
{groupedIssues[group] > 0 && (
|
||||
<div key={index}>
|
||||
<div
|
||||
className="flex items-center justify-between gap-2 text-sm cursor-pointer"
|
||||
className="flex items-center justify-between gap-2 text-13 cursor-pointer"
|
||||
onClick={() => {
|
||||
handleFiltersUpdate([{ property: "state_group", operator: "in", value: [group] }]);
|
||||
}}
|
||||
|
|
@ -78,9 +78,9 @@ export const ActiveCycleProgress = observer(function ActiveCycleProgress(props:
|
|||
backgroundColor: PROGRESS_STATE_GROUPS_DETAILS[index].color,
|
||||
}}
|
||||
/>
|
||||
<span className="text-custom-text-300 capitalize font-medium w-16">{group}</span>
|
||||
<span className="text-tertiary capitalize font-medium w-16">{group}</span>
|
||||
</div>
|
||||
<span className="text-custom-text-300">{`${groupedIssues[group]} ${
|
||||
<span className="text-tertiary">{`${groupedIssues[group]} ${
|
||||
groupedIssues[group] > 1 ? "Work items" : "Work item"
|
||||
}`}</span>
|
||||
</div>
|
||||
|
|
@ -89,7 +89,7 @@ export const ActiveCycleProgress = observer(function ActiveCycleProgress(props:
|
|||
</>
|
||||
))}
|
||||
{cycle.cancelled_issues > 0 && (
|
||||
<span className="flex items-center gap-2 text-sm text-custom-text-300">
|
||||
<span className="flex items-center gap-2 text-13 text-tertiary">
|
||||
<span>
|
||||
{`${cycle.cancelled_issues} cancelled ${
|
||||
cycle.cancelled_issues > 1 ? "work items are" : "work item is"
|
||||
|
|
@ -105,7 +105,7 @@ export const ActiveCycleProgress = observer(function ActiveCycleProgress(props:
|
|||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Loader className="flex flex-col min-h-[17rem] gap-5 bg-custom-background-100 border border-custom-border-200 rounded-lg">
|
||||
<Loader className="flex flex-col min-h-[17rem] gap-5 bg-surface-1 border border-subtle rounded-lg">
|
||||
<Loader.Item width="100%" height="100%" />
|
||||
</Loader>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ export const CycleAnalyticsProgress = observer(function CycleAnalyticsProgress(p
|
|||
|
||||
if (!cycleDetails) return <></>;
|
||||
return (
|
||||
<div className="border-t border-custom-border-200 space-y-4 py-5">
|
||||
<div className="border-t border-subtle space-y-4 py-5">
|
||||
<Disclosure defaultOpen>
|
||||
{({ open }) => (
|
||||
<div className="flex flex-col">
|
||||
|
|
@ -106,9 +106,7 @@ export const CycleAnalyticsProgress = observer(function CycleAnalyticsProgress(p
|
|||
{isCycleDateValid ? (
|
||||
<div className="relative w-full flex justify-between items-center gap-2">
|
||||
<Disclosure.Button className="relative flex items-center gap-2 w-full">
|
||||
<div className="font-medium text-custom-text-200 text-sm">
|
||||
{t("project_cycles.active_cycle.progress")}
|
||||
</div>
|
||||
<div className="font-medium text-secondary text-13">{t("project_cycles.active_cycle.progress")}</div>
|
||||
</Disclosure.Button>
|
||||
<Disclosure.Button className="ml-auto">
|
||||
{open ? (
|
||||
|
|
@ -120,13 +118,11 @@ export const CycleAnalyticsProgress = observer(function CycleAnalyticsProgress(p
|
|||
</div>
|
||||
) : (
|
||||
<div className="relative w-full flex justify-between items-center gap-2">
|
||||
<div className="font-medium text-custom-text-200 text-sm">
|
||||
{t("project_cycles.active_cycle.progress")}
|
||||
</div>
|
||||
<div className="font-medium text-secondary text-13">{t("project_cycles.active_cycle.progress")}</div>
|
||||
</div>
|
||||
)}
|
||||
<Transition show={open}>
|
||||
<Disclosure.Panel className="flex flex-col divide-y divide-custom-border-200">
|
||||
<Disclosure.Panel className="flex flex-col divide-y divide-subtle-1">
|
||||
{cycleStartDate && cycleEndDate ? (
|
||||
<>
|
||||
{isCycleDateValid && (
|
||||
|
|
@ -160,7 +156,7 @@ export const CycleAnalyticsProgress = observer(function CycleAnalyticsProgress(p
|
|||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className="my-2 py-2 text-sm text-custom-text-350 bg-custom-background-90 rounded-md px-2 w-full">
|
||||
<div className="my-2 py-2 text-13 text-tertiary bg-surface-2 rounded-md px-2 w-full">
|
||||
{t("no_data_yet")}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -122,18 +122,16 @@ export const CycleProgressStats = observer(function CycleProgressStats(props: TC
|
|||
className={cn(
|
||||
`flex w-full items-center justify-between gap-2 rounded-md p-1`,
|
||||
roundedTab ? `rounded-3xl` : `rounded-md`,
|
||||
noBackground ? `` : `bg-custom-background-90`,
|
||||
size === "xs" ? `text-xs` : `text-sm`
|
||||
noBackground ? `` : `bg-surface-2`,
|
||||
size === "xs" ? `text-11` : `text-13`
|
||||
)}
|
||||
>
|
||||
{PROGRESS_STATS.map((stat) => (
|
||||
<Tab
|
||||
className={cn(
|
||||
`p-1 w-full text-custom-text-100 outline-none focus:outline-none cursor-pointer transition-all`,
|
||||
roundedTab ? `rounded-3xl border border-custom-border-200` : `rounded`,
|
||||
stat.key === currentTab
|
||||
? "bg-custom-background-100 text-custom-text-300"
|
||||
: "text-custom-text-400 hover:text-custom-text-300"
|
||||
`p-1 w-full text-primary outline-none focus:outline-none cursor-pointer transition-all`,
|
||||
roundedTab ? `rounded-3xl border border-subtle` : `rounded-sm`,
|
||||
stat.key === currentTab ? "bg-surface-1 text-tertiary" : "text-placeholder hover:text-tertiary"
|
||||
)}
|
||||
key={stat.key}
|
||||
onClick={() => setCycleTab(stat.key)}
|
||||
|
|
@ -142,7 +140,7 @@ export const CycleProgressStats = observer(function CycleProgressStats(props: TC
|
|||
</Tab>
|
||||
))}
|
||||
</Tab.List>
|
||||
<Tab.Panels className="py-3 text-custom-text-200">
|
||||
<Tab.Panels className="py-3 text-secondary">
|
||||
<Tab.Panel key={"stat-states"}>
|
||||
<StateGroupStatComponent
|
||||
distribution={distributionStateData}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export const CycleSidebarDetails = observer(function CycleSidebarDetails(props:
|
|||
<div className="flex flex-col gap-5 w-full">
|
||||
{cycleDetails?.description && (
|
||||
<TextArea
|
||||
className="outline-none ring-none w-full max-h-max bg-transparent !p-0 !m-0 !border-0 resize-none text-sm leading-5 text-custom-text-200"
|
||||
className="outline-none ring-none w-full max-h-max bg-transparent !p-0 !m-0 !border-0 resize-none text-13 leading-5 text-secondary"
|
||||
value={cycleDetails.description}
|
||||
disabled
|
||||
/>
|
||||
|
|
@ -72,24 +72,24 @@ export const CycleSidebarDetails = observer(function CycleSidebarDetails(props:
|
|||
|
||||
<div className="flex flex-col gap-5 pb-6 pt-2.5">
|
||||
<div className="flex items-center justify-start gap-1">
|
||||
<div className="flex w-2/5 items-center justify-start gap-2 text-custom-text-300">
|
||||
<div className="flex w-2/5 items-center justify-start gap-2 text-tertiary">
|
||||
<SquareUser className="h-4 w-4" />
|
||||
<span className="text-base">{t("lead")}</span>
|
||||
<span className="text-14">{t("lead")}</span>
|
||||
</div>
|
||||
<div className="flex w-3/5 items-center rounded-sm">
|
||||
<div className="flex w-3/5 items-center rounded-xs">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<Avatar name={cycleOwnerDetails?.display_name} src={getFileURL(cycleOwnerDetails?.avatar_url ?? "")} />
|
||||
<span className="text-sm text-custom-text-200">{cycleOwnerDetails?.display_name}</span>
|
||||
<span className="text-13 text-secondary">{cycleOwnerDetails?.display_name}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-start gap-1">
|
||||
<div className="flex w-2/5 items-center justify-start gap-2 text-custom-text-300">
|
||||
<div className="flex w-2/5 items-center justify-start gap-2 text-tertiary">
|
||||
<MembersPropertyIcon className="h-4 w-4" />
|
||||
<span className="text-base">{t("members")}</span>
|
||||
<span className="text-14">{t("members")}</span>
|
||||
</div>
|
||||
<div className="flex w-3/5 items-center rounded-sm">
|
||||
<div className="flex w-3/5 items-center rounded-xs">
|
||||
<div className="flex items-center gap-2.5">
|
||||
{cycleDetails?.assignee_ids && cycleDetails.assignee_ids.length > 0 ? (
|
||||
<>
|
||||
|
|
@ -108,19 +108,19 @@ export const CycleSidebarDetails = observer(function CycleSidebarDetails(props:
|
|||
</AvatarGroup>
|
||||
</>
|
||||
) : (
|
||||
<span className="px-1.5 text-sm text-custom-text-300">{t("no_assignee")}</span>
|
||||
<span className="px-1.5 text-13 text-tertiary">{t("no_assignee")}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-start gap-1">
|
||||
<div className="flex w-2/5 items-center justify-start gap-2 text-custom-text-300">
|
||||
<div className="flex w-2/5 items-center justify-start gap-2 text-tertiary">
|
||||
<WorkItemsIcon className="h-4 w-4" />
|
||||
<span className="text-base">{t("work_items")}</span>
|
||||
<span className="text-14">{t("work_items")}</span>
|
||||
</div>
|
||||
<div className="flex w-3/5 items-center">
|
||||
<span className="px-1.5 text-sm text-custom-text-300">{issueCount}</span>
|
||||
<span className="px-1.5 text-13 text-tertiary">{issueCount}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -129,12 +129,12 @@ export const CycleSidebarDetails = observer(function CycleSidebarDetails(props:
|
|||
*/}
|
||||
{isEstimatePointValid && !isCompleted && (
|
||||
<div className="flex items-center justify-start gap-1">
|
||||
<div className="flex w-2/5 items-center justify-start gap-2 text-custom-text-300">
|
||||
<div className="flex w-2/5 items-center justify-start gap-2 text-tertiary">
|
||||
<WorkItemsIcon className="h-4 w-4" />
|
||||
<span className="text-base">{t("points")}</span>
|
||||
<span className="text-14">{t("points")}</span>
|
||||
</div>
|
||||
<div className="flex w-3/5 items-center">
|
||||
<span className="px-1.5 text-sm text-custom-text-300">{issueEstimatePointCount}</span>
|
||||
<span className="px-1.5 text-13 text-tertiary">{issueEstimatePointCount}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -153,22 +153,22 @@ export const CycleSidebarHeader = observer(function CycleSidebarHeader(props: Pr
|
|||
|
||||
return (
|
||||
<>
|
||||
<div className="sticky z-10 top-0 pt-2 flex items-center justify-between bg-custom-sidebar-background-100">
|
||||
<div className="sticky z-10 top-0 pt-2 flex items-center justify-between bg-surface-1">
|
||||
<div className="flex items-center justify-center size-5">
|
||||
<button
|
||||
className="flex size-4 items-center justify-center rounded-full bg-custom-border-200"
|
||||
className="flex size-4 items-center justify-center rounded-full bg-layer-3"
|
||||
onClick={() => handleClose()}
|
||||
>
|
||||
<ChevronRightIcon className="h-3 w-3 stroke-2 text-white" />
|
||||
<ChevronRightIcon className="h-3 w-3 stroke-2 text-on-color" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 w-full">
|
||||
<div className="flex items-start justify-between gap-3 pt-2">
|
||||
<h4 className="w-full break-words text-xl font-semibold text-custom-text-100">{cycleDetails.name}</h4>
|
||||
<h4 className="w-full break-words text-18 font-semibold text-primary">{cycleDetails.name}</h4>
|
||||
{currentCycle && (
|
||||
<span
|
||||
className="flex h-6 min-w-20 px-3 items-center justify-center rounded text-center text-xs font-medium"
|
||||
className="flex h-6 min-w-20 px-3 items-center justify-center rounded-sm text-center text-11 font-medium"
|
||||
style={{
|
||||
color: currentCycle.color,
|
||||
backgroundColor: `${currentCycle.color}20`,
|
||||
|
|
@ -223,7 +223,7 @@ export const CycleSidebarHeader = observer(function CycleSidebarHeader(props: Pr
|
|||
)}
|
||||
/>
|
||||
{projectUTCOffset && (
|
||||
<span className="rounded-md text-xs px-2 cursor-default py-1 bg-custom-background-80 text-custom-text-300">
|
||||
<span className="rounded-md text-11 px-2 cursor-default py-1 bg-layer-1 text-tertiary">
|
||||
{projectUTCOffset}
|
||||
</span>
|
||||
)}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue