在 shadcn-ui button 組件,增加 loading spinner

前言

關於 shadcn-ui 這款 UI Library 可以參考shadcn-ui ── 可能是改變遊戲規則的 UI Library

官方提供的 Button 並沒有 loading-spinner 的效果,但在 MUI 或 chakra UI 都有
畢竟是很容易使用上的功能

而 shadcn-ui 直接放置原始碼在專案裡,要客制化相當容易,完全不需要額外的學習成本
簡單的調整型別與組件裡的行為,馬上就增加好 loading-spinner,甚至想要改成喜歡的 icon 也非常容易!

手動增加

直接看 Code 說明!

+ import { Loader2 } from 'lucide-react';


// ... 略過前面 cva 部份

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
+  loading?: boolean;
}

// 將 loading 與 children 從 props 取出來
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
+  ({ className, variant, size, asChild = false, loading, children, ...props }, ref) => {
    const Comp = asChild ? Slot : 'button';
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
+        disabled={loading}
        ref={ref}
        {...props}
      >
+        {loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : children}
      </Comp>
    );
  },
);
Button.displayName = 'Button';

直接貼上使用

以下提供修改後的原始碼,方便直接貼上使用

import { Loader2 } from 'lucide-react';


export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
  loading?: boolean;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, loading, children, ...props }, ref) => {
    const Comp = asChild ? Slot : 'button';
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        disabled={loading}
        ref={ref}
        {...props}
      >
        {loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : children}
      </Comp>
    );
  },
);
Button.displayName = 'Button';

心得

shadcn-ui 透過 Cli 產生組件原始碼放在專案裡的作法
若本身相當熟悉 tailwind 與 React,幾乎是零學習成本的修改底層,輕易做到高度客制化

真的非常方便!