npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sanring/gx-ui

v5.0.1

Published

一個功能完整的 Angular UI 組件庫,提供按鈕、Toast 通知、標籤、載入動畫、圖標等常用組件。採用 Angular Standalone Components 架構實現,內建 Signal 狀態管理,適合用於各種現代化 Angular 應用程式。

Readme

GX-UI

一個功能完整的 Angular UI 組件庫,提供按鈕、Toast 通知、標籤、載入動畫、圖標等常用組件。採用 Angular Standalone Components 架構實現,內建 Signal 狀態管理,適合用於各種現代化 Angular 應用程式。

✅ 已完成的組件

核心組件

  • GxButton - 按鈕組件(支援多種樣式、變體、動作模式)
  • GxToast - Toast 通知組件(支援自動關閉、倒數計時、動作按鈕)
  • GxToastService - Toast 服務(統一管理通知狀態)
  • GxTag - 標籤組件(支援可移除標籤、不同樣式)
  • GxOverlay - 遮罩層組件(支援鍵盤事件、背景點擊)
  • GxLoading - 載入組件(整合 Spinner 和 Bar 兩種樣式)
  • GxLoadingSpinner - 旋轉載入動畫
  • GxLoadingBar - 條狀載入動畫
  • GxIcon - 圖標組件(支援 Lucide Icons 和內建圖標)

類型定義

  • GxButtonIntent - 按鈕意圖類型(info, success, warning, error)
  • GxButtonVariant - 按鈕變體類型(filled, outline, soft, ghost, tag)
  • GxButtonStyle - 按鈕樣式配置
  • GxAction - 按鈕動作介面
  • GxToast - Toast 通知介面
  • GxToastCategory - Toast 分類類型
  • GxLoadingType - 載入類型(bar, spinner)
  • GxLoadingSize - 載入大小(xs, sm, md, lg, xl)
  • GxLoadingSpeed - 載入速度(slow, normal, fast)

📦 安裝

npm install @sanring/gx-ui

可選依賴

如果你想使用 Lucide 圖標:

npm install lucide-angular

注意: lucide-angular可選的。你可以使用內建圖標而無需安裝它。

🎯 使用方式

GxButton - 按鈕組件

基本範例

import { Component } from '@angular/core';
import { GxButton } from '@sanring/gx-ui';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [GxButton],
  template: `
    <gx-button
      [intent]="'info'"
      [variant]="'filled'"
      (pressed)="onButtonClick($event)">
      點擊我
    </gx-button>
  `
})
export class ExampleComponent {
  onButtonClick(event: MouseEvent) {
    console.log('按鈕被點擊了!', event);
  }
}

使用 Action 模式

import { Component } from '@angular/core';
import { GxButton, GxAction } from '@sanring/gx-ui';

@Component({
  selector: 'app-action-example',
  standalone: true,
  imports: [GxButton],
  template: `
    <gx-button [action]="saveAction">
      {{ saveAction.label }}
    </gx-button>
  `
})
export class ActionExampleComponent {
  saveAction: GxAction = {
    label: '儲存',
    handler: () => this.save(),
    disabled: false
  };

  save() {
    console.log('儲存資料...');
  }
}

不同樣式和變體

@Component({
  template: `
    <!-- 不同意圖 -->
    <gx-button [intent]="'info'">資訊</gx-button>
    <gx-button [intent]="'success'">成功</gx-button>
    <gx-button [intent]="'warning'">警告</gx-button>
    <gx-button [intent]="'error'">錯誤</gx-button>

    <!-- 不同變體 -->
    <gx-button [variant]="'filled'">填滿</gx-button>
    <gx-button [variant]="'outline'">外框</gx-button>
    <gx-button [variant]="'soft'">柔和</gx-button>
    <gx-button [variant]="'ghost'">幽靈</gx-button>

    <!-- 自定義樣式 -->
    <gx-button
      [styleTokens]="{ px: 16, py: 10, radius: 12 }"
      [tooltip]="'這是提示文字'">
      自定義樣式
    </gx-button>

    <!-- 禁用狀態 -->
    <gx-button [disabled]="true">禁用按鈕</gx-button>
  `
})

GxToast - Toast 通知組件

設置 Toast 提供者

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideToasts } from '@sanring/gx-ui';

export const appConfig: ApplicationConfig = {
  providers: [
    provideToasts({
      max: 5,                    // 最多顯示 5 個 toast
      defaultDuration: 3000,     // 預設 3 秒自動關閉
      width: '360px'             // Toast 寬度
    })
  ]
};

在 App 中添加 Toast Host

// app.component.ts
import { Component } from '@angular/core';
import { GxToastHost } from '@sanring/gx-ui';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [GxToastHost],
  template: `
    <router-outlet></router-outlet>
    <gx-toast-host></gx-toast-host>  <!-- Toast 容器 -->
  `
})
export class AppComponent {}

使用 Toast Service

import { Component, inject } from '@angular/core';
import { GxToastService } from '@sanring/gx-ui';
import { GxButton } from '@sanring/gx-ui';

@Component({
  selector: 'app-toast-example',
  standalone: true,
  imports: [GxButton],
  template: `
    <gx-button (pressed)="showSuccess()">顯示成功訊息</gx-button>
    <gx-button (pressed)="showError()">顯示錯誤訊息</gx-button>
    <gx-button (pressed)="showWithAction()">顯示帶動作的 Toast</gx-button>
    <gx-button (pressed)="showWithCountdown()">顯示倒數計時 Toast</gx-button>
  `
})
export class ToastExampleComponent {
  private toastService = inject(GxToastService);

  showSuccess() {
    this.toastService.show({
      kind: 'success',
      title: '成功',
      message: '操作已成功完成!',
      duration: 3000
    });
  }

  showError() {
    this.toastService.show({
      kind: 'error',
      title: '錯誤',
      message: '發生錯誤,請稍後再試。',
      duration: 5000
    });
  }

  showWithAction() {
    this.toastService.show({
      kind: 'info',
      title: '通知',
      message: '您有新的訊息',
      action: {
        label: '查看',
        handler: () => console.log('查看訊息')
      },
      duration: 0  // 不自動關閉
    });
  }

  showWithCountdown() {
    this.toastService.show({
      kind: 'warning',
      title: '警告',
      message: '此操作將在倒數結束後執行',
      countdown: true,  // 顯示倒數計時
      duration: 10000   // 10 秒
    });
  }
}

GxTag - 標籤組件

import { Component } from '@angular/core';
import { GxTag } from '@sanring/gx-ui';

@Component({
  selector: 'app-tag-example',
  standalone: true,
  imports: [GxTag],
  template: `
    <!-- 基本標籤 -->
    <gx-tag [intent]="'info'">資訊標籤</gx-tag>
    <gx-tag [intent]="'success'">成功標籤</gx-tag>
    <gx-tag [intent]="'warning'">警告標籤</gx-tag>
    <gx-tag [intent]="'error'">錯誤標籤</gx-tag>

    <!-- 可移除標籤 -->
    <gx-tag
      [intent]="'info'"
      [removable]="true"
      (remove)="onRemove()">
      可移除標籤
    </gx-tag>

    <!-- 可點擊標籤 -->
    <gx-tag
      [intent]="'success'"
      (onClick)="onTagClick($event)">
      可點擊標籤
    </gx-tag>

    <!-- 禁用標籤 -->
    <gx-tag [disabled]="true">禁用標籤</gx-tag>
  `
})
export class TagExampleComponent {
  onRemove() {
    console.log('標籤被移除');
  }

  onTagClick(event: MouseEvent) {
    console.log('標籤被點擊', event);
  }
}

GxLoading - 載入組件

import { Component } from '@angular/core';
import { GxLoading } from '@sanring/gx-ui';

@Component({
  selector: 'app-loading-example',
  standalone: true,
  imports: [GxLoading],
  template: `
    <!-- Bar 樣式載入 -->
    <gx-loading
      [type]="'bar'"
      [size]="'md'"
      [speed]="'normal'">
    </gx-loading>

    <!-- Spinner 樣式載入 -->
    <gx-loading
      [type]="'spinner'"
      [size]="'lg'"
      [color]="'#3b82f6'">
    </gx-loading>

    <!-- 不同大小 -->
    <gx-loading [type]="'bar'" [size]="'xs'"></gx-loading>
    <gx-loading [type]="'bar'" [size]="'sm'"></gx-loading>
    <gx-loading [type]="'bar'" [size]="'md'"></gx-loading>
    <gx-loading [type]="'bar'" [size]="'lg'"></gx-loading>
    <gx-loading [type]="'bar'" [size]="'xl'"></gx-loading>

    <!-- Spinner 漸層色 -->
    <gx-loading
      [type]="'spinner'"
      [colors]="['#3b82f6', '#8b5cf6', '#ec4899']"
      [strokeWidth]="6">
    </gx-loading>

    <!-- 自定義 Bar 數量 -->
    <gx-loading
      [type]="'bar'"
      [barsAmount]="8">
    </gx-loading>
  `
})
export class LoadingExampleComponent {}

GxOverlay - 遮罩層組件

import { Component, signal } from '@angular/core';
import { GxOverlay } from '@sanring/gx-ui';
import { GxButton } from '@sanring/gx-ui';

@Component({
  selector: 'app-overlay-example',
  standalone: true,
  imports: [GxOverlay, GxButton],
  template: `
    <gx-button (pressed)="showOverlay.set(true)">顯示遮罩層</gx-button>

    @if (showOverlay()) {
      <gx-overlay
        [closeOnEsc]="true"
        (backdropClick)="showOverlay.set(false)">
        <div class="modal-content">
          <h2>對話框內容</h2>
          <p>這是一個使用 Overlay 的對話框範例</p>
          <gx-button (pressed)="showOverlay.set(false)">關閉</gx-button>
        </div>
      </gx-overlay>
    }
  `,
  styles: [`
    .modal-content {
      background: white;
      padding: 2rem;
      border-radius: 0.5rem;
      max-width: 400px;
    }
  `]
})
export class OverlayExampleComponent {
  showOverlay = signal(false);
}

GxIcon - 圖標組件

import { Component } from '@angular/core';
import { GxIcon } from '@sanring/gx-ui';

@Component({
  selector: 'app-icon-example',
  standalone: true,
  imports: [GxIcon],
  template: `
    <!-- 使用內建圖標(無需 lucide-angular) -->
    <gx-icon [name]="'x'" [size]="24"></gx-icon>
    <gx-icon [name]="'plus'" [size]="24"></gx-icon>
    <gx-icon [name]="'minus'" [size]="24"></gx-icon>
    <gx-icon [name]="'chevron-left'" [size]="24"></gx-icon>
    <gx-icon [name]="'chevron-right'" [size]="24"></gx-icon>

    <!-- 使用 Lucide 圖標(需要安裝 lucide-angular) -->
    <gx-icon [name]="'home'" [size]="24"></gx-icon>
    <gx-icon [name]="'settings'" [size]="24"></gx-icon>

    <!-- 自定義樣式 -->
    <gx-icon
      [name]="'x'"
      [size]="32"
      [strokeWidth]="3"
      [color]="'#ef4444'">
    </gx-icon>

    <!-- 帶無障礙標籤 -->
    <gx-icon
      [name]="'home'"
      [ariaLabel]="'首頁'"
      [size]="'1.5rem'">
    </gx-icon>
  `
})
export class IconExampleComponent {}

📖 API 文檔

GxButton

Inputs

| 屬性 | 類型 | 預設值 | 說明 | |------|------|--------|------| | action | GxAction \| undefined | undefined | 行為導向模式(包含 label 和 handler) | | intent | GxButtonIntent | 'info' | 按鈕意圖(info, success, warning, error) | | variant | GxButtonVariant | 'filled' | 按鈕變體(filled, outline, soft, ghost, tag) | | disabled | boolean | false | 是否禁用 | | styleTokens | GxButtonStyle | {px:12, py:8, radius:8} | 自定義樣式配置 | | tooltip | string \| undefined | undefined | 滑鼠 hover 顯示的提示文字 | | needsAriaLabel | boolean | false | 若內容沒有可見文字時設為 true |

Outputs

| 事件 | 類型 | 說明 | |------|------|------| | pressed | EventEmitter<MouseEvent> | 按鈕點擊事件 |

GxAction 介面

interface GxAction {
  label?: string;           // 按鈕標籤
  handler?: () => void;     // 點擊處理函數
  disabled?: boolean;       // 是否禁用
}

GxButtonStyle 介面

interface GxButtonStyle {
  px?: number;           // 水平 padding
  py?: number;           // 垂直 padding
  radius?: number;       // 邊框圓角
  background?: string;   // 背景色
  foreground?: string;   // 前景色
}

GxToastService

方法

// 顯示 Toast
show(partial: Omit<GxToast, 'id'>): number

// 關閉指定 Toast
dismiss(id: number): void

// 清除所有 Toast
clear(): void

GxToast 介面

interface GxToast {
  id: number;                   // Toast ID(自動生成)
  kind: GxToastCategory;        // 類型(info, success, warning, error)
  message: string;              // 訊息內容
  title?: string;               // 標題
  icon?: string;                // 自定義圖標
  duration?: number;            // 持續時間(毫秒),0 表示不自動關閉
  dismissible?: boolean;        // 是否可手動關閉
  countdown?: boolean;          // 是否顯示倒數計時
  action?: {                    // 動作按鈕
    label: string;
    handler: () => void;
  };
}

GxTag

Inputs

| 屬性 | 類型 | 預設值 | 說明 | |------|------|--------|------| | intent | GxButtonIntent | 'info' | 標籤樣式意圖 | | removable | boolean | false | 是否可移除 | | disabled | boolean | false | 是否禁用 |

Outputs

| 事件 | 類型 | 說明 | |------|------|------| | onClick | EventEmitter<MouseEvent> | 標籤點擊事件 | | remove | EventEmitter<void> | 移除按鈕點擊事件 |

GxOverlay

Inputs

| 屬性 | 類型 | 預設值 | 說明 | |------|------|--------|------| | closeOnEsc | boolean | true | 是否按 ESC 鍵關閉 | | backdropClickFn | () => void | () => {} | 背景點擊回調函數 |

Outputs

| 事件 | 類型 | 說明 | |------|------|------| | backdropClick | EventEmitter<void> | 背景點擊事件 |

GxLoading

Inputs

| 屬性 | 類型 | 預設值 | 說明 | |------|------|--------|------| | type | GxLoadingType | 'bar' | 載入類型(bar, spinner) | | size | GxLoadingSize | 'md' | 大小(xs, sm, md, lg, xl) | | speed | GxLoadingSpeed | 'normal' | 速度(slow, normal, fast) | | color | string \| undefined | undefined | 自定義顏色 | | colors | string[] \| undefined | undefined | 漸層色陣列(僅 spinner) | | strokeWidth | number | 4 | 線條寬度(1-8,僅 spinner) | | barsAmount | number | 5 | Bar 數量(3-12,僅 bar) |

GxLoadingSpinner

Inputs

| 屬性 | 類型 | 預設值 | 說明 | |------|------|--------|------| | color | string \| undefined | undefined | 單色設定 | | colors | string[] \| undefined | undefined | 漸層色陣列 | | strokeWidth | number | 4 | 線條寬度(1-8) |

GxLoadingBar

Inputs

| 屬性 | 類型 | 預設值 | 說明 | |------|------|--------|------| | color | string \| undefined | undefined | 自定義顏色 | | barsAmount | number | 5 | Bar 數量(3-12) |

GxIcon

Inputs

| 屬性 | 類型 | 預設值 | 說明 | |------|------|--------|------| | name | string | 必填 | 圖標名稱 | | ariaLabel | string \| null | null | 無障礙標籤 | | size | string \| number | 16 | 大小 | | unit | string | 'px' | 單位 | | strokeWidth | number | 2 | 線條寬度 | | color | string \| null | null | 顏色 |

內建圖標

  • x - 關閉圖標
  • plus - 加號
  • minus - 減號
  • chevron-left - 左箭頭
  • chevron-right - 右箭頭

🎨 樣式自定義

GxButton 樣式變數

:root {
  /* 按鈕顏色 */
  --gx-button-info-bg: #3b82f6;
  --gx-button-success-bg: #10b981;
  --gx-button-warning-bg: #f59e0b;
  --gx-button-error-bg: #ef4444;

  /* 按鈕文字 */
  --gx-button-text-color: #ffffff;

  /* 按鈕邊框 */
  --gx-button-border-width: 1px;

  /* 按鈕陰影 */
  --gx-button-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);

  /* Hover 效果 */
  --gx-button-hover-brightness: 1.1;
}

GxToast 樣式變數

:root {
  /* Toast 容器 */
  --gx-toast-width: 320px;
  --gx-toast-max-height: 500px;
  --gx-toast-padding: 1rem;

  /* Toast 項目 */
  --gx-toast-item-bg: #ffffff;
  --gx-toast-item-border-radius: 0.5rem;
  --gx-toast-item-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);

  /* Toast 顏色 */
  --gx-toast-info-color: #3b82f6;
  --gx-toast-success-color: #10b981;
  --gx-toast-warning-color: #f59e0b;
  --gx-toast-error-color: #ef4444;
}

GxLoading 樣式變數

:root {
  /* 載入顏色 */
  --gx-bar-bc: #3b82f6;
  --gx-spinner-color: #3b82f6;

  /* 大小(由組件自動設定) */
  --gx-base-height: 40px;
  --gx-bar-gap: 4px;
  --gx-radius: 4px;
  --gx-spinner-size: 40px;

  /* 動畫速度(由組件自動設定) */
  --gx-bar-duration: 1.2s;
}

🔄 技術實現

本組件庫採用 Angular 18+ 的 Standalone Components 架構,提供現代化且高效能的 UI 解決方案。

組件架構

| 組件名稱 | 功能說明 | |---------|---------| | GxButton | 按鈕組件,支援多種樣式變體與行為模式 | | GxToastHost | Toast 容器組件,管理 Toast 顯示 | | GxToastService | Toast 服務,統一管理通知狀態與生命週期 | | GxTag | 標籤組件,支援可移除與點擊互動 | | GxOverlay | 遮罩層組件,提供模態對話框背景 | | GxLoading | 載入組件,整合 Spinner 和 Bar 兩種樣式 | | GxLoadingSpinner | 旋轉載入動畫組件 | | GxLoadingBar | 條狀載入動畫組件 | | GxIcon | 圖標組件,支援 Lucide Icons 與內建圖標 |

核心特點

  • 響應式狀態管理: 完全使用 Angular Signals,提供高效能的資料響應
  • 靈活的樣式系統: 支援 CSS 變數與 Input 屬性兩種客製化方式
  • 完整的 TypeScript 類型: 提供完整的類型定義,提升開發體驗
  • 無障礙支援: 遵循 ARIA 標準,提供良好的可訪問性
  • 模組化設計: 每個組件獨立,可按需引入
  • 現代化動畫: 使用 CSS 動畫與過渡效果,流暢自然

使用場景

  • 應用程式按鈕與互動元素
  • Toast 通知與訊息提示
  • 標籤管理與篩選
  • 載入狀態指示
  • 對話框與彈出層
  • 圖標顯示

🛠️ 開發

# 安裝依賴
cd packages/gx-ui
npm install

# 構建
npm run build

# 查看生成的文件
ls -la ../../dist/gx-ui

🤝 貢獻

歡迎提交 Issue 與 Pull Request 來改進組件功能!

📄 授權

MIT