mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-23 19:05:16 +02:00
refactor: replace button elements with Button component for improved consistency and styling across additional UI components
This commit is contained in:
parent
13b2e874f6
commit
c77babf39b
25 changed files with 148 additions and 92 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { Search, X } from "lucide-react";
|
||||
import type { FC } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
import { TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
|
@ -76,14 +77,16 @@ export const ConnectorDialogHeader: FC<ConnectorDialogHeaderProps> = ({
|
|||
onChange={(e) => onSearchChange(e.target.value)}
|
||||
/>
|
||||
{searchQuery && (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
type="button"
|
||||
onClick={() => onSearchChange("")}
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground hover:text-accent-foreground transition-colors"
|
||||
className="absolute right-1.5 top-1/2 size-7 -translate-y-1/2 text-muted-foreground transition-colors hover:bg-transparent hover:text-accent-foreground"
|
||||
aria-label="Clear search"
|
||||
>
|
||||
<X className="size-4" />
|
||||
</button>
|
||||
<X data-icon="inline-start" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { AlertTriangle, X } from "lucide-react";
|
||||
import type { FC } from "react";
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface ConnectorWarningBannerProps {
|
||||
|
|
@ -42,14 +43,16 @@ export const ConnectorWarningBanner: FC<ConnectorWarningBannerProps> = ({
|
|||
)}
|
||||
</div>
|
||||
{onDismiss && (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
type="button"
|
||||
onClick={handleDismiss}
|
||||
className="shrink-0 p-0.5 rounded hover:bg-yellow-500/20 transition-colors"
|
||||
className="size-6 shrink-0 rounded p-0 transition-colors hover:bg-yellow-500/20"
|
||||
aria-label="Dismiss warning"
|
||||
>
|
||||
<X className="size-3.5 text-yellow-700 dark:text-yellow-300" />
|
||||
</button>
|
||||
<X data-icon="inline-start" className="text-yellow-700 dark:text-yellow-300" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -90,14 +90,15 @@ export const ConnectorConnectView: FC<ConnectorConnectViewProps> = ({
|
|||
<div className="flex-1 flex flex-col min-h-0 overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="flex-shrink-0 px-6 sm:px-12 pt-8 sm:pt-10">
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={onBack}
|
||||
className="flex items-center gap-2 text-xs sm:text-sm text-muted-foreground hover:text-accent-foreground mb-6 w-fit"
|
||||
className="mb-6 h-auto w-fit justify-start gap-2 px-0 py-0 text-xs text-muted-foreground hover:bg-transparent hover:text-accent-foreground sm:text-sm"
|
||||
>
|
||||
<ArrowLeft className="size-4" />
|
||||
<ArrowLeft data-icon="inline-start" />
|
||||
Back to connectors
|
||||
</button>
|
||||
</Button>
|
||||
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<div className="flex h-14 w-14 items-center justify-center rounded-xl border border-slate-400/30">
|
||||
|
|
|
|||
|
|
@ -206,14 +206,15 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
|
|||
)}
|
||||
>
|
||||
{/* Back button */}
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={onBack}
|
||||
className="flex items-center gap-2 text-xs sm:text-sm text-muted-foreground hover:text-accent-foreground mb-6 w-fit"
|
||||
className="mb-6 h-auto w-fit justify-start gap-2 px-0 py-0 text-xs text-muted-foreground hover:bg-transparent hover:text-accent-foreground sm:text-sm"
|
||||
>
|
||||
<ArrowLeft className="size-4" />
|
||||
<ArrowLeft data-icon="inline-start" />
|
||||
Back to connectors
|
||||
</button>
|
||||
</Button>
|
||||
|
||||
{/* Connector header */}
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-4 mb-6">
|
||||
|
|
|
|||
|
|
@ -128,14 +128,15 @@ export const IndexingConfigurationView: FC<IndexingConfigurationViewProps> = ({
|
|||
>
|
||||
{/* Back button - only show if not from OAuth */}
|
||||
{!isFromOAuth && (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={onSkip}
|
||||
className="flex items-center gap-2 text-xs sm:text-sm text-muted-foreground hover:text-accent-foreground mb-6 w-fit"
|
||||
className="mb-6 h-auto w-fit justify-start gap-2 px-0 py-0 text-xs text-muted-foreground hover:bg-transparent hover:text-accent-foreground sm:text-sm"
|
||||
>
|
||||
<ArrowLeft className="size-4" />
|
||||
<ArrowLeft data-icon="inline-start" />
|
||||
Back to connectors
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* Success header */}
|
||||
|
|
|
|||
|
|
@ -216,14 +216,15 @@ export const YouTubeCrawlerView: FC<YouTubeCrawlerViewProps> = ({ searchSpaceId,
|
|||
<div className="flex-1 flex flex-col min-h-0 overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="shrink-0 px-6 sm:px-12 pt-8 sm:pt-10">
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={onBack}
|
||||
className="flex items-center gap-2 text-xs sm:text-sm text-muted-foreground hover:text-accent-foreground mb-6 w-fit"
|
||||
className="mb-6 h-auto w-fit justify-start gap-2 px-0 py-0 text-xs text-muted-foreground hover:bg-transparent hover:text-accent-foreground sm:text-sm"
|
||||
>
|
||||
<ArrowLeft className="size-4" />
|
||||
<ArrowLeft data-icon="inline-start" />
|
||||
Back to connectors
|
||||
</button>
|
||||
</Button>
|
||||
|
||||
<div className="flex items-center gap-4 mb-6">
|
||||
<div className="flex h-14 w-14 items-center justify-center rounded-xl border border-slate-400/30">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import type { MouseEventHandler, ReactNode } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
@ -60,13 +61,14 @@ export function MentionChip({
|
|||
const isInteractive = Boolean(onClick) && !disabled;
|
||||
|
||||
const chip = (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
aria-label={ariaLabel ?? label}
|
||||
className={cn(
|
||||
"inline-flex max-w-[220px] items-center gap-1.5 rounded-md border bg-background px-2 py-0.5 align-middle text-xs font-medium text-foreground leading-5 transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
||||
"h-auto max-w-[220px] justify-start gap-1.5 rounded-md border bg-background px-2 py-0.5 align-middle text-xs leading-5 text-foreground shadow-none transition-colors focus-visible:ring-1 focus-visible:ring-ring",
|
||||
isInteractive
|
||||
? "cursor-pointer hover:bg-accent hover:text-accent-foreground"
|
||||
: "cursor-default",
|
||||
|
|
@ -76,7 +78,7 @@ export function MentionChip({
|
|||
>
|
||||
<span className="inline-flex shrink-0 text-muted-foreground">{icon}</span>
|
||||
<span className="truncate">{label}</span>
|
||||
</button>
|
||||
</Button>
|
||||
);
|
||||
|
||||
if (!tooltip) return chip;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import type { ReasoningMessagePartComponent } from "@assistant-ui/react";
|
|||
import { ChevronRightIcon } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
|
|
@ -45,11 +46,12 @@ export const ReasoningMessagePart: ReasoningMessagePartComponent = ({ text, stat
|
|||
return (
|
||||
<div className="mx-auto w-full max-w-(--thread-max-width) px-2 py-2">
|
||||
<div className="rounded-lg">
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={() => setIsOpen((prev) => !prev)}
|
||||
className={cn(
|
||||
"flex w-full items-center gap-1.5 text-left text-sm transition-colors",
|
||||
"h-auto w-full justify-start gap-1.5 p-0 text-left text-sm font-normal transition-colors hover:bg-transparent",
|
||||
"text-muted-foreground hover:text-accent-foreground"
|
||||
)}
|
||||
>
|
||||
|
|
@ -59,9 +61,10 @@ export const ReasoningMessagePart: ReasoningMessagePartComponent = ({ text, stat
|
|||
<span>{headerLabel}</span>
|
||||
)}
|
||||
<ChevronRightIcon
|
||||
className={cn("size-4 transition-transform duration-200", isOpen && "rotate-90")}
|
||||
data-icon="inline-end"
|
||||
className={cn("transition-transform duration-200", isOpen && "rotate-90")}
|
||||
/>
|
||||
</button>
|
||||
</Button>
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
|
|
|
|||
|
|
@ -330,8 +330,15 @@ const PendingScreenImageStrip: FC = () => {
|
|||
key={url}
|
||||
className="group relative h-14 w-14 shrink-0 overflow-hidden rounded-md border border-border/50 bg-muted"
|
||||
>
|
||||
{/* biome-ignore lint/performance/noImgElement: data URL thumbnails from capture */}
|
||||
<img src={url} alt="" className="size-full object-cover" draggable={false} />
|
||||
<Image
|
||||
src={url}
|
||||
alt="Pending screenshot preview"
|
||||
fill
|
||||
sizes="56px"
|
||||
className="object-cover"
|
||||
draggable={false}
|
||||
unoptimized
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => setUrls((prev) => prev.filter((_, i) => i !== index))}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { MemberMentionItemProps } from "./types";
|
||||
|
||||
|
|
@ -25,10 +26,11 @@ export function MemberMentionItem({
|
|||
const displayName = member.displayName || member.email.split("@")[0];
|
||||
|
||||
return (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
className={cn(
|
||||
"flex w-full items-center gap-3 px-3 py-2 text-left transition-colors",
|
||||
"h-auto w-full justify-start gap-3 rounded-none px-3 py-2 text-left transition-colors",
|
||||
isHighlighted ? "bg-primary/15 text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground"
|
||||
)}
|
||||
onClick={() => onSelect(member)}
|
||||
|
|
@ -44,6 +46,6 @@ export function MemberMentionItem({
|
|||
<span className="truncate text-sm font-medium">{displayName}</span>
|
||||
<span className="truncate text-xs text-muted-foreground">{member.email}</span>
|
||||
</div>
|
||||
</button>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ export const DEFAULT_SHORTCUTS = {
|
|||
export function Kbd({ keys, className }: { keys: string[]; className?: string }) {
|
||||
return (
|
||||
<span className={cn("inline-flex items-center gap-0.5", className)}>
|
||||
{keys.map((key, i) => (
|
||||
{keys.map((key) => (
|
||||
<kbd
|
||||
key={`${key}-${i}`}
|
||||
key={key}
|
||||
className={cn(
|
||||
"inline-flex h-6 min-w-6 items-center justify-center rounded border bg-muted px-1 font-mono text-[11px] font-medium text-muted-foreground",
|
||||
key.length > 3 && "px-1.5"
|
||||
|
|
@ -136,14 +136,15 @@ export function ShortcutRecorder({
|
|||
<RotateCcw className="size-3" />
|
||||
</Button>
|
||||
)}
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
ref={inputRef}
|
||||
type="button"
|
||||
onClick={() => setRecording(true)}
|
||||
onKeyDown={handleKeyDown}
|
||||
onBlur={() => setRecording(false)}
|
||||
className={cn(
|
||||
"flex h-7 items-center gap-0.5 rounded-md border px-2 transition-all focus:outline-none",
|
||||
"h-7 justify-start gap-0.5 rounded-md border px-2 transition-all",
|
||||
recording
|
||||
? "border-primary bg-primary/5 ring-2 ring-primary/20"
|
||||
: "border-input bg-muted/40 hover:bg-muted"
|
||||
|
|
@ -156,7 +157,7 @@ export function ShortcutRecorder({
|
|||
) : (
|
||||
<Kbd keys={displayKeys} />
|
||||
)}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import type React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
|
|
@ -22,7 +23,7 @@ interface SidebarButtonProps {
|
|||
}
|
||||
|
||||
const baseClassName = cn(
|
||||
"group/sidebar-button relative flex h-9 items-center rounded-md mx-2 px-2 text-sm text-left",
|
||||
"group/sidebar-button relative h-9 justify-start gap-0 rounded-md mx-2 px-2 text-sm text-left",
|
||||
"transition-colors hover:bg-accent hover:text-accent-foreground",
|
||||
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
||||
);
|
||||
|
|
@ -49,7 +50,8 @@ export function SidebarButton({
|
|||
: (expandedIconNode ?? <Icon className="h-3.5 w-3.5 shrink-0" />);
|
||||
|
||||
const button = (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
aria-label={isCollapsed ? label : undefined}
|
||||
|
|
@ -100,7 +102,7 @@ export function SidebarButton({
|
|||
)}
|
||||
|
||||
<span className="sr-only">{label}</span>
|
||||
</button>
|
||||
</Button>
|
||||
);
|
||||
|
||||
const renderTooltip = isCollapsed || !!tooltipContent;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { AnimatePresence, motion } from "motion/react";
|
|||
import type React from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Pricing } from "@/components/pricing";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const demoPlans = [
|
||||
|
|
@ -264,7 +265,7 @@ function PricingFAQ() {
|
|||
|
||||
<div ref={containerRef} className="relative mt-16 flex w-full flex-col gap-12 px-4 md:px-8">
|
||||
{faqData.map((section) => (
|
||||
<div key={section.title + "faq"}>
|
||||
<div key={`${section.title}faq`}>
|
||||
<h3 className="mb-6 text-lg font-medium text-neutral-800 dark:text-neutral-200">
|
||||
{section.title}
|
||||
</h3>
|
||||
|
|
@ -275,7 +276,7 @@ function PricingFAQ() {
|
|||
|
||||
return (
|
||||
<div
|
||||
key={id + "faq-item"}
|
||||
key={`${id}faq-item`}
|
||||
className={cn(
|
||||
"relative rounded-lg transition-all duration-200",
|
||||
isActive
|
||||
|
|
@ -291,10 +292,11 @@ function PricingFAQ() {
|
|||
<GridLineVertical className="-right-[2px] left-auto" offset="100px" />
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={() => toggleQuestion(id)}
|
||||
className="flex w-full items-center justify-between px-4 py-4 text-left"
|
||||
className="h-auto w-full justify-between rounded-lg px-4 py-4 text-left hover:bg-transparent"
|
||||
>
|
||||
<span className="text-sm font-medium text-neutral-700 md:text-base dark:text-neutral-300">
|
||||
{item.question}
|
||||
|
|
@ -306,7 +308,7 @@ function PricingFAQ() {
|
|||
>
|
||||
<IconPlus className="size-5 text-neutral-500 dark:text-neutral-400" />
|
||||
</motion.div>
|
||||
</button>
|
||||
</Button>
|
||||
<AnimatePresence initial={false}>
|
||||
{isActive && (
|
||||
<motion.div
|
||||
|
|
|
|||
|
|
@ -194,13 +194,14 @@ export function FolderWatchDialog({
|
|||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={handleSelectFolder}
|
||||
className="flex flex-1 w-full items-center justify-center gap-2 rounded-lg border-2 border-dashed border-muted-foreground/30 text-sm text-muted-foreground transition-colors hover:border-foreground/50 hover:text-accent-foreground"
|
||||
className="h-auto flex-1 w-full gap-2 rounded-lg border-2 border-dashed border-muted-foreground/30 bg-transparent text-sm text-muted-foreground transition-colors hover:border-foreground/50 hover:bg-transparent hover:text-accent-foreground"
|
||||
>
|
||||
Browse for a folder
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{selectedFolder && (
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { motion } from "motion/react";
|
|||
import { useTheme } from "next-themes";
|
||||
import { useCallback, useEffect, useId, useState } from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -706,10 +707,12 @@ export const ThemeToggleButton = ({
|
|||
const clipPathId = `theme-toggle-clip-${clipId}`;
|
||||
|
||||
return (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
type="button"
|
||||
className={cn(
|
||||
"size-10 cursor-pointer rounded-full p-2 transition-all duration-300 active:scale-95 bg-transparent",
|
||||
"size-10 cursor-pointer rounded-full bg-transparent p-2 transition-all duration-300 hover:bg-transparent active:scale-95",
|
||||
isDark ? "text-white" : "text-black",
|
||||
className
|
||||
)}
|
||||
|
|
@ -720,6 +723,7 @@ export const ThemeToggleButton = ({
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
aria-hidden="true"
|
||||
className="size-full"
|
||||
fill="currentColor"
|
||||
strokeLinecap="round"
|
||||
viewBox="0 0 32 32"
|
||||
|
|
@ -759,7 +763,7 @@ export const ThemeToggleButton = ({
|
|||
</motion.g>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { ExternalLink, Globe } from "lucide-react";
|
||||
import NextImage from "next/image";
|
||||
import * as React from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { openSafeNavigationHref, sanitizeHref } from "../shared/media";
|
||||
import { cn, Popover, PopoverContent, PopoverTrigger } from "./_adapter";
|
||||
import type { CitationVariant, SerializableCitation } from "./schema";
|
||||
|
|
@ -126,7 +127,8 @@ export function Citation(props: CitationProps) {
|
|||
return (
|
||||
<Popover open={open}>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
aria-label={title}
|
||||
data-tool-ui-id={id}
|
||||
|
|
@ -135,7 +137,7 @@ export function Citation(props: CitationProps) {
|
|||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
className={cn(
|
||||
"inline-flex cursor-pointer items-center gap-1.5 rounded-md px-2 py-1",
|
||||
"h-auto cursor-pointer gap-1.5 rounded-md px-2 py-1",
|
||||
"bg-muted/60 text-sm outline-none",
|
||||
"transition-colors duration-150",
|
||||
"hover:bg-accent hover:text-accent-foreground",
|
||||
|
|
@ -145,7 +147,7 @@ export function Citation(props: CitationProps) {
|
|||
>
|
||||
{iconElement}
|
||||
<span className="text-muted-foreground">{domain}</span>
|
||||
</button>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
side="top"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { z } from "zod";
|
|||
import { openReportPanelAtom, reportPanelAtom } from "@/atoms/chat/report-panel.atom";
|
||||
import { PlateEditor } from "@/components/editor/plate-editor";
|
||||
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useMediaQuery } from "@/hooks/use-media-query";
|
||||
import { baseApiService } from "@/lib/apis/base-api.service";
|
||||
|
||||
|
|
@ -215,10 +216,11 @@ function ReportCard({
|
|||
<div
|
||||
className={`my-4 max-w-lg overflow-hidden rounded-2xl border bg-muted/30 transition-[box-shadow] duration-300 ${isActive ? "ring-1 ring-primary/50" : ""}`}
|
||||
>
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={handleOpen}
|
||||
className="w-full text-left transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus-visible:outline-none cursor-pointer"
|
||||
className="h-auto w-full flex-col items-stretch justify-start gap-0 rounded-2xl p-0 text-left font-normal whitespace-normal transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus-visible:outline-none cursor-pointer"
|
||||
>
|
||||
<div className="px-5 pt-5 pb-4 select-none">
|
||||
<p className="text-sm font-semibold text-foreground line-clamp-2">
|
||||
|
|
@ -262,7 +264,7 @@ function ReportCard({
|
|||
<p className="text-sm text-muted-foreground italic">No content available</p>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|||
import { z } from "zod";
|
||||
import { openReportPanelAtom, reportPanelAtom } from "@/atoms/chat/report-panel.atom";
|
||||
import { TextShimmerLoader } from "@/components/prompt-kit/loader";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useMediaQuery } from "@/hooks/use-media-query";
|
||||
import { baseApiService } from "@/lib/apis/base-api.service";
|
||||
import { getAuthHeaders } from "@/lib/auth-utils";
|
||||
|
|
@ -281,10 +282,11 @@ function ResumeCard({
|
|||
<div
|
||||
className={`my-4 max-w-lg overflow-hidden rounded-2xl border bg-muted/30 transition-[box-shadow] duration-300 ${isActive ? "ring-1 ring-primary/50" : ""}`}
|
||||
>
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
onClick={handleOpen}
|
||||
className="w-full text-left transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus-visible:outline-none cursor-pointer select-none"
|
||||
className="h-auto w-full flex-col items-stretch justify-start gap-0 rounded-2xl p-0 text-left font-normal whitespace-normal transition-colors hover:bg-accent hover:text-accent-foreground focus:outline-none focus-visible:outline-none cursor-pointer select-none"
|
||||
>
|
||||
<div className="px-5 pt-5 pb-4">
|
||||
<p className="text-sm font-semibold text-foreground line-clamp-2">{title}</p>
|
||||
|
|
@ -316,7 +318,7 @@ function ResumeCard({
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import type { TCalloutElement } from "platejs";
|
|||
import { PlateElement, type PlateElementProps, useEditorPlugin } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const calloutVariants = cva("my-1 flex w-full items-start gap-2 rounded-lg border p-4", {
|
||||
|
|
@ -24,7 +25,10 @@ const calloutVariants = cva("my-1 flex w-full items-start gap-2 rounded-lg borde
|
|||
},
|
||||
});
|
||||
|
||||
const calloutIcons: Record<string, string> = {
|
||||
const variantCycle = ["info", "warning", "error", "success", "note", "tip"] as const;
|
||||
type CalloutVariant = (typeof variantCycle)[number];
|
||||
|
||||
const calloutIcons: Record<CalloutVariant, string> = {
|
||||
info: "💡",
|
||||
warning: "⚠️",
|
||||
error: "🚨",
|
||||
|
|
@ -33,13 +37,13 @@ const calloutIcons: Record<string, string> = {
|
|||
tip: "💜",
|
||||
};
|
||||
|
||||
const variantCycle = ["info", "warning", "error", "success", "note", "tip"] as const;
|
||||
|
||||
export function CalloutElement({ children, ...props }: PlateElementProps<TCalloutElement>) {
|
||||
const { editor } = useEditorPlugin(CalloutPlugin);
|
||||
const element = props.element;
|
||||
const variant = element.variant || "info";
|
||||
const icon = element.icon || calloutIcons[variant] || "💡";
|
||||
const variant = variantCycle.includes(element.variant as CalloutVariant)
|
||||
? (element.variant as CalloutVariant)
|
||||
: "info";
|
||||
const icon = element.icon || calloutIcons[variant];
|
||||
|
||||
const cycleVariant = React.useCallback(() => {
|
||||
const currentIndex = variantCycle.indexOf(variant as (typeof variantCycle)[number]);
|
||||
|
|
@ -58,17 +62,18 @@ export function CalloutElement({ children, ...props }: PlateElementProps<TCallou
|
|||
return (
|
||||
<PlateElement
|
||||
{...props}
|
||||
className={cn(calloutVariants({ variant: variant as any }), props.className)}
|
||||
className={cn(calloutVariants({ variant }), props.className)}
|
||||
>
|
||||
<button
|
||||
className="mt-0.5 shrink-0 cursor-pointer select-none text-lg leading-none"
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="mt-0.5 h-auto shrink-0 cursor-pointer select-none p-0 text-lg leading-none hover:bg-transparent"
|
||||
contentEditable={false}
|
||||
onClick={cycleVariant}
|
||||
type="button"
|
||||
aria-label="Change callout type"
|
||||
>
|
||||
{icon}
|
||||
</button>
|
||||
</Button>
|
||||
<div className="min-w-0 flex-1">{children}</div>
|
||||
</PlateElement>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -263,11 +263,12 @@ function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<t
|
|||
);
|
||||
}
|
||||
|
||||
function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
|
||||
function SidebarRail({ className, ...props }: React.ComponentProps<typeof Button>) {
|
||||
const { toggleSidebar } = useSidebar();
|
||||
|
||||
return (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
data-sidebar="rail"
|
||||
data-slot="sidebar-rail"
|
||||
aria-label="Toggle Sidebar"
|
||||
|
|
@ -275,7 +276,7 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
|
|||
onClick={toggleSidebar}
|
||||
title="Toggle Sidebar"
|
||||
className={cn(
|
||||
"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex",
|
||||
"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden h-auto w-4 -translate-x-1/2 rounded-none p-0 transition-all ease-linear hover:bg-transparent group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex",
|
||||
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
|
||||
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
||||
"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full",
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
import { useToggleButton, useToggleButtonState } from "@platejs/toggle/react";
|
||||
import { ChevronRightIcon } from "lucide-react";
|
||||
import { PlateElement, type PlateElementProps } from "platejs/react";
|
||||
import * as React from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function ToggleElement({ children, ...props }: PlateElementProps) {
|
||||
|
|
@ -14,7 +14,9 @@ export function ToggleElement({ children, ...props }: PlateElementProps) {
|
|||
|
||||
return (
|
||||
<PlateElement {...props} className="relative py-1 pl-6">
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className={cn(
|
||||
"absolute top-1.5 left-0 flex size-6 cursor-pointer select-none items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
|
||||
)}
|
||||
|
|
@ -25,7 +27,7 @@ export function ToggleElement({ children, ...props }: PlateElementProps) {
|
|||
<ChevronRightIcon
|
||||
className={cn("size-4 transition-transform duration-200", open && "rotate-90")}
|
||||
/>
|
||||
</button>
|
||||
</Button>
|
||||
<div>{children}</div>
|
||||
</PlateElement>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|||
import { ChevronDown } from "lucide-react";
|
||||
import * as React from "react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuRadioGroup,
|
||||
|
|
@ -219,7 +220,8 @@ export function ToolbarSplitButtonSecondary({
|
|||
...props
|
||||
}: React.ComponentPropsWithoutRef<"span"> & VariantProps<typeof dropdownArrowVariants>) {
|
||||
return (
|
||||
<button
|
||||
<Button
|
||||
variant="ghost"
|
||||
type="button"
|
||||
className={cn(
|
||||
dropdownArrowVariants({
|
||||
|
|
@ -233,7 +235,7 @@ export function ToolbarSplitButtonSecondary({
|
|||
{...(props as React.ComponentPropsWithoutRef<"button">)}
|
||||
>
|
||||
<ChevronDown className="size-3.5 text-muted-foreground" data-icon />
|
||||
</button>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue