feat: card checklists (#141)
* feat: setup checklist schema * feat: scaffold checklist router * feat: add create new checklist modal * feat: create new checklist item * feat: toggle checklist item completed state * feat: update checklist name * feat: delete checklist * feat: show checklists progress on cards * feat: tweak light mode styling * feat: focus item form on creation of new checklist * feat: tweak new checklist item form styling * feat: add checklist activity * feat: show checklist progress on public board page * feat: display checklist items on public card modal * chore: add translations
This commit is contained in:
@@ -5,7 +5,7 @@ import LoadingSpinner from "./LoadingSpinner";
|
||||
|
||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
variant?: "primary" | "secondary" | "danger" | "ghost";
|
||||
size?: "sm" | "md" | "lg";
|
||||
size?: "xs" | "sm" | "md" | "lg";
|
||||
isLoading?: boolean;
|
||||
iconLeft?: React.ReactNode;
|
||||
iconRight?: React.ReactNode;
|
||||
@@ -28,6 +28,7 @@ const Button = ({
|
||||
}: ButtonProps) => {
|
||||
const classes = twMerge(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-2 text-sm font-semibold text-light-50 shadow-sm focus-visible:outline-none",
|
||||
size === "xs" && "text-xs px-2 py-1",
|
||||
size === "sm" && "text-xs",
|
||||
size === "lg" && "py-[0.65rem]",
|
||||
fullWidth && "w-full",
|
||||
|
||||
58
apps/web/src/components/CircularProgress.tsx
Normal file
58
apps/web/src/components/CircularProgress.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
interface CircularProgressProps {
|
||||
progress: number; // 0-100
|
||||
size?: "sm" | "md" | "lg";
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const CircularProgress = ({
|
||||
progress,
|
||||
size = "md",
|
||||
className,
|
||||
}: CircularProgressProps) => {
|
||||
const radius = 40;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
const strokeDashoffset = circumference - (progress / 100) * circumference;
|
||||
|
||||
return (
|
||||
<div className={twMerge("relative", className)}>
|
||||
<svg
|
||||
className={twMerge(
|
||||
"-rotate-90 transform",
|
||||
size === "sm" && "h-4 w-4",
|
||||
size === "md" && "h-5 w-5",
|
||||
size === "lg" && "h-8 w-8",
|
||||
)}
|
||||
viewBox="0 0 100 100"
|
||||
>
|
||||
<circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r={radius}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="14"
|
||||
className="text-light-300 dark:text-dark-400"
|
||||
/>
|
||||
<circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r={radius}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="14"
|
||||
strokeDasharray={circumference}
|
||||
strokeDashoffset={strokeDashoffset}
|
||||
strokeLinecap="round"
|
||||
className={twMerge(
|
||||
"transition-all duration-300 ease-in-out",
|
||||
progress === 100 ? "text-green-500" : "text-blue-500",
|
||||
)}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CircularProgress;
|
||||
@@ -15,10 +15,15 @@ import {
|
||||
ReactRenderer,
|
||||
useEditor,
|
||||
} from "@tiptap/react";
|
||||
import { useEffect } from "react";
|
||||
import StarterKit from "@tiptap/starter-kit";
|
||||
import Suggestion from "@tiptap/suggestion";
|
||||
import { forwardRef, useImperativeHandle, useRef, useState } from "react";
|
||||
import {
|
||||
forwardRef,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import {
|
||||
HiH1,
|
||||
HiH2,
|
||||
@@ -547,7 +552,7 @@ export default function Editor({
|
||||
{!readOnly && editor && <EditorBubbleMenu editor={editor} />}
|
||||
<EditorContent
|
||||
editor={editor}
|
||||
className="prose dark:prose-invert prose-sm max-w-none overflow-y-auto [&_blockquote]:!text-xs [&_h1]:!text-lg [&_h2]:!text-base [&_h3]:!text-sm [&_ol]:!text-xs [&_p.is-empty::before]:text-light-900 [&_p.is-empty::before]:dark:text-dark-800 [&_p]:!text-sm [&_p]:text-black [&_p]:dark:text-white [&_ul]:!text-xs"
|
||||
className="prose dark:prose-invert prose-sm max-w-none overflow-y-auto [&_blockquote]:!text-xs [&_h1]:!text-lg [&_h2]:!text-base [&_h3]:!text-sm [&_ol]:!text-xs [&_p.is-empty::before]:text-light-900 [&_p.is-empty::before]:dark:text-dark-800 [&_p]:!text-sm [&_p]:text-light-950 [&_p]:dark:text-dark-950 [&_ul]:!text-xs"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user