{"id":28958554,"url":"https://github.com/ssagroup/ui-kit","last_synced_at":"2026-03-06T18:09:04.626Z","repository":{"id":174723955,"uuid":"648209582","full_name":"ssagroup/ui-kit","owner":"ssagroup","description":"SSA UI kit is an open-source React library offering AI-friendly components to streamline the creation of dashboards and admin panels.","archived":false,"fork":false,"pushed_at":"2025-10-08T20:26:53.000Z","size":5068,"stargazers_count":8,"open_issues_count":47,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-10-09T12:16:36.366Z","etag":null,"topics":["atomic-design","charts","dashboard-templates","emotion","form-builder","react","typescript","ui-components","ui-kit"],"latest_commit_sha":null,"homepage":"https://www.ssa.group/ssa-ui-kit/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ssagroup.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-06-01T12:56:49.000Z","updated_at":"2025-10-03T16:40:29.000Z","dependencies_parsed_at":"2023-10-16T18:36:33.009Z","dependency_job_id":"9fd212b1-5679-4c5a-8e20-a91da79edb82","html_url":"https://github.com/ssagroup/ui-kit","commit_stats":{"total_commits":236,"total_committers":8,"mean_commits":29.5,"dds":0.6101694915254237,"last_synced_commit":"4b212f1feba8467530926e301557ae1a7328f460"},"previous_names":["ssagroup/ui-kit"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ssagroup/ui-kit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssagroup%2Fui-kit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssagroup%2Fui-kit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssagroup%2Fui-kit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssagroup%2Fui-kit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ssagroup","download_url":"https://codeload.github.com/ssagroup/ui-kit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ssagroup%2Fui-kit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001448,"owners_count":26083078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["atomic-design","charts","dashboard-templates","emotion","form-builder","react","typescript","ui-components","ui-kit"],"created_at":"2025-06-23T23:01:00.650Z","updated_at":"2026-03-06T18:09:04.609Z","avatar_url":"https://github.com/ssagroup.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eSSA UI kit\u003c/h1\u003e\n\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/ssagroup/ui-kit/blob/main/CODE_OF_CONDUCT.md)\n\n![image](https://github.com/user-attachments/assets/48a55da6-0609-4575-8c58-34a7ddc5b7f0)\n\nSSA UI kit is an open-source React-based library combining multiple UI Components, Widgets, Blocks, and Forms classified by application area and implemented following Atomic design principles.\n\nSSA UI kit includes Figma design, integration with Firebase and examples of implementation for different business domains.\n\nSSA UI kit was founded and is supported by SSA Group. The SSA UI kit source code is available under the MIT License.\n\nWe regularly post updates, new components, and improvements for the SSA UI kit on our blog: https://www.ssa.group/blog/ssa-ui-kit/\nPlease feel free to follow along.\n\n## 🧠 Mental Model\n\nSSA UI kit components are designed with the following principles:\n\n- **Composable \u0026 Flexible**: Components use composition patterns and compound components for maximum flexibility\n- **Form-First**: Form controls integrate seamlessly with React Hook Form for validation and state management\n- **Type-Safe**: Full TypeScript support with comprehensive type definitions and JSDoc examples\n- **Accessible by Default**: Components follow WAI-ARIA patterns and semantic HTML\n- **Themeable**: Built on Emotion for CSS-in-JS styling with a centralized theme system\n- **Controlled \u0026 Uncontrolled**: Components support both controlled and uncontrolled patterns\n\n### Component Patterns\n\n**Form Controls**: Most form inputs integrate with React Hook Form. Use `register` prop for uncontrolled inputs, or `value`/`onChange` for controlled patterns.\n\n**Compound Components**: Many components like `Table`, `Modal`, `Field`, and `Dropdown` use compound component patterns for flexible composition.\n\n**Status Props**: Components use consistent prop naming like `status` (for validation states), `isDisabled` (for disabled state), and `variant` (for visual variants).\n\n## 🚀 Hero Example\n\nGet started in 60 seconds. Here's a complete example showing Card, Button, Input, and Table working together:\n\n```tsx\nimport { ThemeProvider } from '@emotion/react';\nimport { FormProvider, useForm } from 'react-hook-form';\nimport {\n  Card,\n  CardHeader,\n  CardContent,\n  Button,\n  Input,\n  Typography,\n  Table,\n  TableHead,\n  TableBody,\n  TableRow,\n  TableCell,\n  TableCellHeader,\n  mainTheme,\n  Theme as T,\n} from '@ssa-ui-kit/core';\n\n// TypeScript: Extend Emotion theme types\ndeclare module '@emotion/react' {\n  export interface Theme extends T {}\n}\n\nfunction App() {\n  const methods = useForm();\n  const users = [\n    { id: 1, name: 'John Doe', email: 'john@example.com' },\n    { id: 2, name: 'Jane Smith', email: 'jane@example.com' },\n  ];\n\n  return (\n    \u003cThemeProvider theme={mainTheme}\u003e\n      \u003cFormProvider {...methods}\u003e\n        \u003cCard\u003e\n          \u003cCardHeader\u003e\n            \u003cTypography variant=\"h2\"\u003eUser Management\u003c/Typography\u003e\n          \u003c/CardHeader\u003e\n          \u003cCardContent\u003e\n            \u003cInput\n              name=\"search\"\n              placeholder=\"Search users...\"\n              register={methods.register}\n              css={{ marginBottom: 16 }}\n            /\u003e\n            \u003cTable\u003e\n              \u003cTableHead\u003e\n                \u003cTableRow\u003e\n                  \u003cTableCellHeader\u003eName\u003c/TableCellHeader\u003e\n                  \u003cTableCellHeader\u003eEmail\u003c/TableCellHeader\u003e\n                  \u003cTableCellHeader\u003eActions\u003c/TableCellHeader\u003e\n                \u003c/TableRow\u003e\n              \u003c/TableHead\u003e\n              \u003cTableBody\u003e\n                {users.map((user) =\u003e (\n                  \u003cTableRow key={user.id}\u003e\n                    \u003cTableCell\u003e{user.name}\u003c/TableCell\u003e\n                    \u003cTableCell\u003e{user.email}\u003c/TableCell\u003e\n                    \u003cTableCell\u003e\n                      \u003cButton size=\"small\" text=\"Edit\" /\u003e\n                    \u003c/TableCell\u003e\n                  \u003c/TableRow\u003e\n                ))}\n              \u003c/TableBody\u003e\n            \u003c/Table\u003e\n          \u003c/CardContent\u003e\n        \u003c/Card\u003e\n      \u003c/FormProvider\u003e\n    \u003c/ThemeProvider\u003e\n  );\n}\n```\n\n## 📦 Installation\n\n```bash\n# Core components\nnpm install @ssa-ui-kit/core\n# or\nyarn add @ssa-ui-kit/core\n# or\npnpm add @ssa-ui-kit/core\n\n# Hooks (optional, separate package)\nnpm install @ssa-ui-kit/hooks\n# or\nyarn add @ssa-ui-kit/hooks\n# or\npnpm add @ssa-ui-kit/hooks\n```\n\n\u003e ⚠️ **Vite Users**: See the [Vite Configuration](#-critical-vite-configuration-for-react-hook-form) section below for required setup to avoid `useFormContext()` errors.\n\n### Peer Dependencies\n\nMake sure you have React 19.x, Emotion, and React Hook Form installed:\n\n```bash\nnpm install react@19.x react-dom@19.x @emotion/react @emotion/styled react-hook-form\n```\n\n## ⚠️ CRITICAL: Vite Configuration for React Hook Form\n\n\u003e **🚨 IMPORTANT**: If you're using **Vite** and experiencing `useFormContext() returned null` errors with form components (like `DateRangePicker`, `DatePicker`, etc.), you **MUST** configure Vite to use the CommonJS bundle of `react-hook-form`.\n\n### The Problem\n\nThe UI kit (`@ssa-ui-kit/core`) is built with webpack and uses CommonJS externals. When webpack externalizes `react-hook-form`, it expects the **CommonJS version**. However, Vite defaults to the **ESM bundle** (`index.esm.mjs`). Different module instances = different React contexts, causing `useFormContext()` to return `null` inside UI kit components.\n\n### The Fix\n\nAdd this alias to your `vite.config.ts`:\n\n```typescript\nimport path from 'node:path';\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [react()],\n  resolve: {\n    dedupe: ['react', 'react-dom', 'react-hook-form'],\n    alias: {\n      '@': path.resolve(__dirname, './src'),\n      // ⚠️ CRITICAL: Force CommonJS bundle for react-hook-form\n      // This ensures the UI kit (expecting CommonJS) uses the same instance as your app\n      'react-hook-form': path.resolve(\n        __dirname,\n        './node_modules/react-hook-form/dist/index.cjs.js' // ← CommonJS bundle\n      ),\n    },\n  },\n  optimizeDeps: {\n    include: ['react-hook-form'],\n  },\n});\n```\n\n### Why This Matters\n\nReact contexts are **instance-specific**. Even with the same package version, if the library uses a different module instance (ESM vs CJS), the context won't be shared. Using the CommonJS bundle ensures both your app and the webpack-built UI kit use the **same instance**.\n\n**Related Issue**: [react-hook-form#8281](https://github.com/react-hook-form/react-hook-form/issues/8281)\n\n\u003e **💡 Note**: This only applies to Vite projects. Webpack projects don't need this configuration.\n\n## 🏁 Quick Start\n\n### 1. Set up Theme Provider\n\nWrap your app with `ThemeProvider` from `@emotion/react` and pass `mainTheme`:\n\n```tsx\nimport { ThemeProvider } from '@emotion/react';\nimport { mainTheme, Theme as T } from '@ssa-ui-kit/core';\n\n// TypeScript: Extend Emotion theme types (required for TypeScript projects)\ndeclare module '@emotion/react' {\n  export interface Theme extends T {}\n}\n\nfunction App() {\n  return (\n    \u003cThemeProvider theme={mainTheme}\u003e\n      {/* Your app components */}\n    \u003c/ThemeProvider\u003e\n  );\n}\n```\n\n### 2. TypeScript Setup (if using TypeScript)\n\nIn your main entry file (e.g., `src/index.tsx`), add the theme type augmentation:\n\n```tsx\nimport '@emotion/react';\nimport { Theme as T } from '@ssa-ui-kit/core';\n\ndeclare module '@emotion/react' {\n  export interface Theme extends T {}\n}\n```\n\n\u003e [!TIP]\n\u003e If you are using a monorepo or a custom Vite/Webpack setup, we recommend putting the `declare module '@emotion/react'` block in a global `types/emotion.d.ts` file to keep your components clean.\n\n## 📚 Component Examples\n\n### Button\n\nButtons come in multiple variants, sizes, and can include icons:\n\n```tsx\nimport { Button, Icon } from '@ssa-ui-kit/core';\n\n// Basic button\n\u003cButton text=\"Click me\" variant=\"primary\" size=\"medium\" /\u003e\n\n// Button with icon\n\u003cButton\n  text=\"Save\"\n  startIcon={\u003cIcon name=\"check\" size={16} /\u003e}\n  variant=\"secondary\"\n/\u003e\n\n// Variants: primary, secondary, tertiary, info, attention\n// Sizes: small, medium, large\n```\n\n### Input\n\nForm inputs with validation states and helper text:\n\n```tsx\nimport { Input } from '@ssa-ui-kit/core';\nimport { useForm, FormProvider } from 'react-hook-form';\n\nfunction MyForm() {\n  const methods = useForm();\n  \n  return (\n    \u003cFormProvider {...methods}\u003e\n      \u003cInput\n        name=\"email\"\n        placeholder=\"Enter your email\"\n        status=\"basic\" // or 'error', 'success'\n        helperText=\"We'll never share your email\"\n        showHelperText\n      /\u003e\n    \u003c/FormProvider\u003e\n  );\n}\n```\n\n**Note:** Input components work with `react-hook-form`. Wrap your form with `FormProvider` from `react-hook-form`.\n\n### Table\n\nBuild data tables with sorting, styling, and row actions:\n\n```tsx\nimport {\n  Table,\n  TableHead,\n  TableBody,\n  TableRow,\n  TableCell,\n  TableCellHeader,\n} from '@ssa-ui-kit/core';\n\nfunction UserTable() {\n  const data = [\n    { id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },\n    { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' },\n  ];\n\n  return (\n    \u003cTable\u003e\n      \u003cTableHead\u003e\n        \u003cTableRow\u003e\n          \u003cTableCellHeader\u003eName\u003c/TableCellHeader\u003e\n          \u003cTableCellHeader\u003eEmail\u003c/TableCellHeader\u003e\n          \u003cTableCellHeader\u003eRole\u003c/TableCellHeader\u003e\n        \u003c/TableRow\u003e\n      \u003c/TableHead\u003e\n      \u003cTableBody\u003e\n        {data.map((user) =\u003e (\n          \u003cTableRow key={user.id}\u003e\n            \u003cTableCell\u003e{user.name}\u003c/TableCell\u003e\n            \u003cTableCell\u003e{user.email}\u003c/TableCell\u003e\n            \u003cTableCell\u003e{user.role}\u003c/TableCell\u003e\n          \u003c/TableRow\u003e\n        ))}\n      \u003c/TableBody\u003e\n    \u003c/Table\u003e\n  );\n}\n```\n\n## 🎣 Hooks Examples\n\n### useApi\n\nHandle async data fetching with loading and error states:\n\n```tsx\nimport { useApi } from '@ssa-ui-kit/hooks';\n\nfunction UserList() {\n  const { data, isLoading, error, query } = useApi(\n    async (userId: string) =\u003e {\n      const response = await fetch(`/api/users/${userId}`);\n      return response.json();\n    }\n  );\n\n  useEffect(() =\u003e {\n    query('123');\n  }, []);\n\n  if (isLoading) return \u003cdiv\u003eLoading...\u003c/div\u003e;\n  if (error) return \u003cdiv\u003eError: {error.message}\u003c/div\u003e;\n  return \u003cdiv\u003e{data.name}\u003c/div\u003e;\n}\n```\n\n### useToggle\n\nToggle between multiple values (useful for boolean or multi-state toggles):\n\n```tsx\nimport { useToggle } from '@ssa-ui-kit/hooks';\n\nfunction ToggleExample() {\n  // Boolean toggle (default)\n  const [isOpen, toggleOpen] = useToggle();\n\n  // Multi-state toggle\n  const [theme, toggleTheme] = useToggle(['light', 'dark', 'auto']);\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={() =\u003e toggleOpen()}\u003e\n        {isOpen ? 'Close' : 'Open'}\n      \u003c/button\u003e\n      \u003cbutton onClick={() =\u003e toggleTheme()}\u003e\n        Theme: {theme}\n      \u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n### useWindowSize\n\nTrack window dimensions with reactive updates:\n\n```tsx\nimport { useWindowSize } from '@ssa-ui-kit/hooks';\n\nfunction ResponsiveComponent() {\n  const { width, height } = useWindowSize();\n  const isMobile = width \u003c 768;\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eWindow size: {width}x{height}\u003c/p\u003e\n      {isMobile ? \u003cMobileView /\u003e : \u003cDesktopView /\u003e}\n    \u003c/div\u003e\n  );\n}\n```\n\n### Other Available Hooks\n\n- `useClickOutside` - Detect clicks outside an element\n- `useDebouncedCallback` - Debounce function calls\n- `useThrottledCallback` - Throttle function calls\n- `useClipboard` - Copy to clipboard functionality\n- `useDeviceType` - Detect device type\n- `useResizeObserver` - Observe element size changes\n- `usePaginationRange` - Generate pagination ranges\n\n## 🛠️ Core Technologies\n\nThe project is built using:\n\n- [React](https://react.dev/) 19.x\n- [TypeScript](https://www.typescriptlang.org/)\n- CSS-in-JS with [Emotion](https://emotion.sh/docs/introduction)\n- Charts with [Nivo](https://nivo.rocks/)\n- [Floating UI](https://floating-ui.com/) for tooltips\n- [Storybook](https://storybook.js.org/) for component documentation\n- [pNPM](https://pnpm.io/) as package manager\n\n## 📖 Documentation\n\nFor detailed component documentation, examples, and API references, visit our [Storybook documentation](https://ssagroup.github.io/ui-kit/).\n\n## 🤝 Want to contribute?\n\nPlease refer to our [CONTRIBUTING.md](https://github.com/ssagroup/ui-kit/blob/main/CONTRIBUTING.md).\n\n## 📄 License\n\n[MIT](https://github.com/ssagroup/ui-kit/blob/main/LICENSE)\n\n## 🙏 Thanks\n\n\u003ca href=\"https://www.lost-pixel.com/\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/29632358/168112844-77e76a0d-b96f-4bc8-b753-cd39f4afd428.png\" width=\"100\" height=\"100\" alt=\"Lost Pixel\" /\u003e\u003c/a\u003e\n\nThanks to [Lost Pixel](https://www.lost-pixel.com/) for providing the visual testing platform that helps us review UI changes and catch visual regressions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fssagroup%2Fui-kit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fssagroup%2Fui-kit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fssagroup%2Fui-kit/lists"}