chore: update various components and services for improved functionality and consistency, including formatting adjustments and minor refactors
This commit is contained in:
@@ -13,9 +13,9 @@ interface ErrorMessageProps {
|
||||
retryLabel?: string;
|
||||
}
|
||||
|
||||
export const ErrorMessage = ({
|
||||
errorCode,
|
||||
error,
|
||||
export const ErrorMessage = ({
|
||||
errorCode,
|
||||
error,
|
||||
variant = "default",
|
||||
onRetry,
|
||||
retryLabel,
|
||||
@@ -37,12 +37,7 @@ export const ErrorMessage = ({
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<p>{message}</p>
|
||||
{onRetry && (
|
||||
<Button
|
||||
onClick={onRetry}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="ml-auto"
|
||||
>
|
||||
<Button onClick={onRetry} variant="ghost" size="sm" className="ml-auto">
|
||||
<RefreshCw className="h-3 w-3" />
|
||||
</Button>
|
||||
)}
|
||||
@@ -68,11 +63,11 @@ export const ErrorMessage = ({
|
||||
{t("errors.GENERIC_ERROR")}
|
||||
</h3>
|
||||
<p className="text-sm text-destructive/90 dark:text-red-300/90">{message}</p>
|
||||
|
||||
|
||||
{onRetry && (
|
||||
<Button
|
||||
<Button
|
||||
onClick={onRetry}
|
||||
variant="outline"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="mt-4 border-destructive/30 hover:bg-destructive/10"
|
||||
>
|
||||
|
||||
@@ -24,13 +24,10 @@ const badgeVariants = cva(
|
||||
);
|
||||
|
||||
export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {}
|
||||
|
||||
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
return (
|
||||
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
);
|
||||
return <div className={cn(badgeVariants({ variant }), className)} {...props} />;
|
||||
}
|
||||
|
||||
export { Badge, badgeVariants };
|
||||
|
||||
@@ -138,8 +138,8 @@ export function BookCover({
|
||||
{showOverlay && overlayVariant === "default" && (
|
||||
<div className="absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/60 to-transparent p-4 space-y-2 translate-y-full group-hover:translate-y-0 transition-transform duration-200">
|
||||
<p className="text-sm font-medium text-white text-left line-clamp-2">
|
||||
{book.metadata.title ||
|
||||
(book.metadata.number
|
||||
{book.metadata.title ||
|
||||
(book.metadata.number
|
||||
? t("navigation.volume", { number: book.metadata.number })
|
||||
: "")}
|
||||
</p>
|
||||
@@ -155,8 +155,8 @@ export function BookCover({
|
||||
{showOverlay && overlayVariant === "home" && (
|
||||
<div className="absolute inset-0 bg-black/60 opacity-0 hover:opacity-100 transition-opacity duration-200 flex flex-col justify-end p-3">
|
||||
<h3 className="font-medium text-sm text-white line-clamp-2">
|
||||
{book.metadata.title ||
|
||||
(book.metadata.number
|
||||
{book.metadata.title ||
|
||||
(book.metadata.number
|
||||
? t("navigation.volume", { number: book.metadata.number })
|
||||
: "")}
|
||||
</h3>
|
||||
|
||||
@@ -273,8 +273,8 @@ export function BookOfflineButton({ book, className }: BookOfflineButtonProps) {
|
||||
const buttonTitle = isLoading
|
||||
? `Téléchargement en cours (${Math.round(downloadProgress)}%)`
|
||||
: isAvailableOffline
|
||||
? "Supprimer hors ligne"
|
||||
: "Disponible hors ligne";
|
||||
? "Supprimer hors ligne"
|
||||
: "Disponible hors ligne";
|
||||
|
||||
return (
|
||||
<Button
|
||||
|
||||
@@ -9,9 +9,12 @@ const buttonVariants = cva(
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary/90 backdrop-blur-md text-primary-foreground hover:bg-primary/80",
|
||||
destructive: "bg-destructive/90 backdrop-blur-md text-destructive-foreground hover:bg-destructive/80",
|
||||
outline: "border border-input bg-background/70 backdrop-blur-md hover:bg-accent/80 hover:text-accent-foreground",
|
||||
secondary: "bg-secondary/80 backdrop-blur-md text-secondary-foreground hover:bg-secondary/70",
|
||||
destructive:
|
||||
"bg-destructive/90 backdrop-blur-md text-destructive-foreground hover:bg-destructive/80",
|
||||
outline:
|
||||
"border border-input bg-background/70 backdrop-blur-md hover:bg-accent/80 hover:text-accent-foreground",
|
||||
secondary:
|
||||
"bg-secondary/80 backdrop-blur-md text-secondary-foreground hover:bg-secondary/70",
|
||||
ghost: "hover:bg-accent/80 hover:backdrop-blur-md hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
@@ -30,8 +33,7 @@ const buttonVariants = cva(
|
||||
);
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElemen
|
||||
({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("rounded-lg border bg-card/70 backdrop-blur-md text-card-foreground shadow-sm", className)}
|
||||
className={cn(
|
||||
"rounded-lg border bg-card/70 backdrop-blur-md text-card-foreground shadow-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -26,4 +26,3 @@ const Checkbox = React.forwardRef<
|
||||
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
||||
|
||||
export { Checkbox };
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ const containerVariants = cva("mx-auto px-2 sm:px-6 lg:px-8", {
|
||||
});
|
||||
|
||||
export interface ContainerProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof containerVariants> {
|
||||
extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof containerVariants> {
|
||||
as?: React.ElementType;
|
||||
}
|
||||
|
||||
@@ -44,4 +43,3 @@ const Container = React.forwardRef<HTMLDivElement, ContainerProps>(
|
||||
Container.displayName = "Container";
|
||||
|
||||
export { Container, containerVariants };
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ export const CoverClient = ({
|
||||
const timer = setTimeout(() => {
|
||||
setImageError(false);
|
||||
setIsLoading(true);
|
||||
setRetryCount(prev => prev + 1);
|
||||
setRetryCount((prev) => prev + 1);
|
||||
}, 2000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
@@ -80,9 +80,10 @@ export const CoverClient = ({
|
||||
};
|
||||
|
||||
// Ajouter un timestamp pour forcer le rechargement en cas de retry
|
||||
const imageUrlWithRetry = retryCount > 0
|
||||
? `${imageUrl}${imageUrl.includes('?') ? '&' : '?'}retry=${retryCount}`
|
||||
: imageUrl;
|
||||
const imageUrlWithRetry =
|
||||
retryCount > 0
|
||||
? `${imageUrl}${imageUrl.includes("?") ? "&" : "?"}retry=${retryCount}`
|
||||
: imageUrl;
|
||||
|
||||
if (imageError) {
|
||||
return (
|
||||
|
||||
@@ -30,4 +30,3 @@ const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
|
||||
IconButton.displayName = "IconButton";
|
||||
|
||||
export { IconButton };
|
||||
|
||||
|
||||
@@ -8,18 +8,12 @@ const labelVariants = cva(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
);
|
||||
|
||||
interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement>,
|
||||
VariantProps<typeof labelVariants> {}
|
||||
interface LabelProps
|
||||
extends React.LabelHTMLAttributes<HTMLLabelElement>, VariantProps<typeof labelVariants> {}
|
||||
|
||||
const Label = React.forwardRef<HTMLLabelElement, LabelProps>(
|
||||
({ className, ...props }, ref) => (
|
||||
<label
|
||||
ref={ref}
|
||||
className={cn(labelVariants(), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
const Label = React.forwardRef<HTMLLabelElement, LabelProps>(({ className, ...props }, ref) => (
|
||||
<label ref={ref} className={cn(labelVariants(), className)} {...props} />
|
||||
));
|
||||
Label.displayName = "Label";
|
||||
|
||||
export { Label };
|
||||
|
||||
@@ -25,9 +25,7 @@ const NavButton = React.forwardRef<HTMLButtonElement, NavButtonProps>(
|
||||
<Icon className="mr-2 h-4 w-4" />
|
||||
<span className="truncate">{label}</span>
|
||||
</div>
|
||||
{count !== undefined && (
|
||||
<span className="text-xs text-muted-foreground">{count}</span>
|
||||
)}
|
||||
{count !== undefined && <span className="text-xs text-muted-foreground">{count}</span>}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -36,4 +34,3 @@ const NavButton = React.forwardRef<HTMLButtonElement, NavButtonProps>(
|
||||
NavButton.displayName = "NavButton";
|
||||
|
||||
export { NavButton };
|
||||
|
||||
|
||||
@@ -6,10 +6,11 @@ interface ProgressBarProps {
|
||||
|
||||
export function ProgressBar({ progress, total, type }: ProgressBarProps) {
|
||||
const percentage = Math.round((progress / total) * 100);
|
||||
|
||||
const barColor = type === "series"
|
||||
? "bg-gradient-to-r from-purple-500 to-pink-500"
|
||||
: "bg-gradient-to-r from-blue-500 to-cyan-500";
|
||||
|
||||
const barColor =
|
||||
type === "series"
|
||||
? "bg-gradient-to-r from-purple-500 to-pink-500"
|
||||
: "bg-gradient-to-r from-blue-500 to-cyan-500";
|
||||
return (
|
||||
<div className="absolute bottom-0 left-0 right-0 px-3 py-2 bg-black/70 backdrop-blur-md border-t border-white/10">
|
||||
<div className="h-2 bg-white/30 rounded-full overflow-hidden">
|
||||
|
||||
@@ -10,9 +10,7 @@ const RadioGroup = React.forwardRef<
|
||||
React.ElementRef<typeof RadioGroupPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => {
|
||||
return (
|
||||
<RadioGroupPrimitive.Root className={cn("grid gap-2", className)} {...props} ref={ref} />
|
||||
);
|
||||
return <RadioGroupPrimitive.Root className={cn("grid gap-2", className)} {...props} ref={ref} />;
|
||||
});
|
||||
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
||||
|
||||
@@ -38,4 +36,3 @@ const RadioGroupItem = React.forwardRef<
|
||||
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
||||
|
||||
export { RadioGroup, RadioGroupItem };
|
||||
|
||||
|
||||
@@ -76,10 +76,7 @@ const ScrollContainer = React.forwardRef<HTMLDivElement, ScrollContainerProps>(
|
||||
<div
|
||||
ref={scrollContainerRef}
|
||||
onScroll={handleScroll}
|
||||
className={cn(
|
||||
"flex gap-4 overflow-x-auto scrollbar-hide scroll-smooth pb-4",
|
||||
className
|
||||
)}
|
||||
className={cn("flex gap-4 overflow-x-auto scrollbar-hide scroll-smooth pb-4", className)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
@@ -102,4 +99,3 @@ const ScrollContainer = React.forwardRef<HTMLDivElement, ScrollContainerProps>(
|
||||
ScrollContainer.displayName = "ScrollContainer";
|
||||
|
||||
export { ScrollContainer };
|
||||
|
||||
|
||||
@@ -42,4 +42,3 @@ const Section = React.forwardRef<HTMLElement, SectionProps>(
|
||||
Section.displayName = "Section";
|
||||
|
||||
export { Section };
|
||||
|
||||
|
||||
@@ -24,4 +24,3 @@ const Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(
|
||||
Separator.displayName = "Separator";
|
||||
|
||||
export { Separator };
|
||||
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Skeleton({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) {
|
||||
return (
|
||||
<div
|
||||
className={cn("animate-pulse rounded-md bg-muted", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
||||
return <div className={cn("animate-pulse rounded-md bg-muted", className)} {...props} />;
|
||||
}
|
||||
|
||||
export { Skeleton };
|
||||
|
||||
|
||||
@@ -69,10 +69,7 @@ export function SliderControl({
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
{description && (
|
||||
<p className="text-xs text-muted-foreground">{description}</p>
|
||||
)}
|
||||
{description && <p className="text-xs text-muted-foreground">{description}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import * as SliderPrimitive from "@radix-ui/react-slider"
|
||||
import * as React from "react";
|
||||
import * as SliderPrimitive from "@radix-ui/react-slider";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const Slider = React.forwardRef<
|
||||
React.ElementRef<typeof SliderPrimitive.Root>,
|
||||
@@ -11,11 +11,8 @@ const Slider = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SliderPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex w-full touch-auto select-none items-center",
|
||||
className
|
||||
)}
|
||||
style={{ touchAction: 'pan-x' }}
|
||||
className={cn("relative flex w-full touch-auto select-none items-center", className)}
|
||||
style={{ touchAction: "pan-x" }}
|
||||
{...props}
|
||||
>
|
||||
<SliderPrimitive.Track className="relative h-3 w-full grow overflow-hidden rounded-full bg-secondary">
|
||||
@@ -23,8 +20,7 @@ const Slider = React.forwardRef<
|
||||
</SliderPrimitive.Track>
|
||||
<SliderPrimitive.Thumb className="block h-6 w-6 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:scale-110 active:scale-105 touch-manipulation cursor-pointer" />
|
||||
</SliderPrimitive.Root>
|
||||
))
|
||||
Slider.displayName = SliderPrimitive.Root.displayName
|
||||
|
||||
export { Slider }
|
||||
));
|
||||
Slider.displayName = SliderPrimitive.Root.displayName;
|
||||
|
||||
export { Slider };
|
||||
|
||||
@@ -21,19 +21,14 @@ const statusBadgeVariants = cva("flex items-center gap-1", {
|
||||
});
|
||||
|
||||
export interface StatusBadgeProps
|
||||
extends Omit<BadgeProps, "variant">,
|
||||
VariantProps<typeof statusBadgeVariants> {
|
||||
extends Omit<BadgeProps, "variant">, VariantProps<typeof statusBadgeVariants> {
|
||||
icon?: LucideIcon;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const StatusBadge = ({ status, icon: Icon, children, className, ...props }: StatusBadgeProps) => {
|
||||
return (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={cn(statusBadgeVariants({ status }), className)}
|
||||
{...props}
|
||||
>
|
||||
<Badge variant="outline" className={cn(statusBadgeVariants({ status }), className)} {...props}>
|
||||
{Icon && <Icon className="w-4 h-4" />}
|
||||
{children}
|
||||
</Badge>
|
||||
@@ -41,4 +36,3 @@ const StatusBadge = ({ status, icon: Icon, children, className, ...props }: Stat
|
||||
};
|
||||
|
||||
export { StatusBadge, statusBadgeVariants };
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
import * as React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface SwitchProps
|
||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "role" | "aria-checked"> {
|
||||
interface SwitchProps extends Omit<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
"type" | "role" | "aria-checked"
|
||||
> {
|
||||
onCheckedChange?: (checked: boolean) => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,7 @@ import { cn } from "@/lib/utils";
|
||||
const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(
|
||||
({ className, ...props }, ref) => (
|
||||
<div className="relative w-full overflow-auto">
|
||||
<table
|
||||
ref={ref}
|
||||
className={cn("w-full caption-bottom text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
<table ref={ref} className={cn("w-full caption-bottom text-sm", className)} {...props} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
@@ -37,7 +33,10 @@ const TableFooter = React.forwardRef<
|
||||
>(({ className, ...props }, ref) => (
|
||||
<tfoot
|
||||
ref={ref}
|
||||
className={cn("border-t bg-muted/50 backdrop-blur-md font-medium [&>tr]:last:border-b-0", className)}
|
||||
className={cn(
|
||||
"border-t bg-muted/50 backdrop-blur-md font-medium [&>tr]:last:border-b-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
@@ -93,4 +92,3 @@ const TableCaption = React.forwardRef<
|
||||
TableCaption.displayName = "TableCaption";
|
||||
|
||||
export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ const toastVariants = cva(
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "border border-border/40 bg-background/70 backdrop-blur-md text-foreground shadow-lg",
|
||||
default:
|
||||
"border border-border/40 bg-background/70 backdrop-blur-md text-foreground shadow-lg",
|
||||
destructive:
|
||||
"destructive group border-destructive/20 bg-destructive/70 backdrop-blur-md text-destructive-foreground font-medium",
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user