JSPM

@ttoss/components

2.7.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 495
  • Score
    100M100P100Q98223F
  • License MIT

React components for ttoss ecosystem.

Package Exports

  • @ttoss/components/Accordion
  • @ttoss/components/Drawer
  • @ttoss/components/FileUploader
  • @ttoss/components/InstallPwa
  • @ttoss/components/JsonEditor
  • @ttoss/components/JsonView
  • @ttoss/components/List
  • @ttoss/components/Markdown
  • @ttoss/components/Menu
  • @ttoss/components/Modal
  • @ttoss/components/NavList
  • @ttoss/components/NotificationCard
  • @ttoss/components/NotificationsMenu
  • @ttoss/components/Search
  • @ttoss/components/Table
  • @ttoss/components/Tabs
  • @ttoss/components/Toast

Readme

@ttoss/components

React components for the ttoss ecosystem. ESM only package.

Quick Start

pnpm add @ttoss/components @ttoss/ui @emotion/react @ttoss/react-hooks

📖 View all components in Storybook

Components Overview

All components are theme-aware and integrate seamlessly with @ttoss/ui.

Accordion

Collapsible content sections. 📖 Docs

import {
  Accordion,
  AccordionItem,
  AccordionItemButton,
  AccordionItemHeading,
  AccordionItemPanel,
} from '@ttoss/components/Accordion';

<Accordion allowMultipleExpanded>
  <AccordionItem>
    <AccordionItemHeading>
      <AccordionItemButton>Section Title</AccordionItemButton>
    </AccordionItemHeading>
    <AccordionItemPanel>Section content</AccordionItemPanel>
  </AccordionItem>
</Accordion>;

Drawer

Slide-out panels from screen edges. 📖 Docs

import { Drawer } from '@ttoss/components/Drawer';

<Drawer open={isOpen} direction="right" size="300px">
  <div>Drawer content</div>
</Drawer>;

FileUploader

Controlled file uploader with drag-and-drop support. Displays uploaded files with previews, clickable links, and remove functionality. 📖 Docs

import { FileUploader } from '@ttoss/components/FileUploader';
import { useState } from 'react';

const [files, setFiles] = useState([
  {
    id: 'file-1',
    name: 'document.pdf',
    url: 'https://example.com/files/document.pdf',
  },
  {
    id: 'file-2',
    name: 'image.jpg',
    imageUrl: 'https://example.com/images/thumb.jpg', // Optional preview
    url: 'https://example.com/files/image.jpg',
  },
]);

<FileUploader
  // Required: Upload handler
  onUpload={async (file, onProgress) => {
    // Your upload logic here
    onProgress?.(50); // Report progress
    const result = await uploadToServer(file);
    return { url: result.url, id: result.id, name: result.name };
  }}
  // Controlled files list
  files={files}
  // Callbacks
  onUploadComplete={(file, result) => {
    setFiles([...files, { id: result.id, name: file.name, url: result.url }]);
  }}
  onRemove={(file, index) => {
    setFiles(files.filter((_, i) => i !== index));
  }}
  // Optional: Validation
  accept="image/*,.pdf"
  maxSize={10 * 1024 * 1024} // 10MB
  maxFiles={5}
/>;

Key Features:

  • Controlled component: Pass files prop to display uploaded files
  • Clickable file names: Names are links that open the file URL
  • Image previews: Show thumbnails when imageUrl is provided
  • Remove functionality: Each file has a remove button
  • Upload callbacks: onUploadStart, onUploadProgress, onUploadComplete, onUploadError
  • Validation: File type, size, and quantity limits
  • Drag-and-drop: Native drag-and-drop support

InstallPwa

PWA installation prompt component. 📖 Docs

import { InstallPwa } from '@ttoss/components/InstallPwa';

<InstallPwa />;

JsonEditor

JSON editor component. Re-exports from json-edit-react. 📖 Docs

import { JsonEditor } from '@ttoss/components/JsonEditor';

<JsonEditor data={jsonData} setData={setJsonData} />;

JsonView

JSON viewer component. Re-exports from react-json-view-lite. 📖 Docs

import { JsonView } from '@ttoss/components/JsonView';

<JsonView data={jsonData} />;

List

Unordered lists with customizable items. 📖 Docs

import { List, ListItem } from '@ttoss/components/List';

<List>
  <ListItem>First item</ListItem>
  <ListItem>Second item</ListItem>
</List>;

Markdown

Render markdown content with theme integration. 📖 Docs

import { Markdown } from '@ttoss/components/Markdown';

<Markdown
  components={{
    a: ({ children, ...props }) => <Link {...props}>{children}</Link>,
  }}
>
  # Heading Some **bold** text
</Markdown>;

Dropdown menus with customizable triggers. 📖 Docs

import { Menu } from '@ttoss/components/Menu';

<Menu trigger={<Button>Open Menu</Button>}>
  <Menu.Item onClick={() => {}}>Action 1</Menu.Item>
  <Menu.Item onClick={() => {}}>Action 2</Menu.Item>
</Menu>;

Navigation lists for sidebars, menus, and dropdowns with icons, grouping, and routing integration. 📖 Docs

import { NavList } from '@ttoss/components/NavList';

// Simple navigation
<NavList
  items={[
    { id: '1', label: 'Home', href: '/', icon: 'mdi:home' },
    { id: '2', label: 'Profile', href: '/profile', icon: 'mdi:account' },
    { id: '3', label: 'Settings', href: '/settings', icon: 'mdi:cog' },
  ]}
  variant="sidebar"
/>

// With groups
<NavList
  groups={[
    {
      id: 'main',
      label: 'Main Menu',
      items: [
        { id: '1', label: 'Dashboard', href: '/dashboard', icon: 'mdi:view-dashboard' },
        { id: '2', label: 'Analytics', href: '/analytics', icon: 'mdi:chart-line' },
      ],
    },
    {
      id: 'settings',
      label: 'Settings',
      items: [
        { id: '3', label: 'Account', href: '/account', icon: 'mdi:account-cog' },
      ],
      divider: true, // Divider after group
    },
  ]}
/>

// With Next.js routing
import NextLink from 'next/link';

<NavList
  items={items}
  LinkComponent={NextLink}
  onItemClick={(item) => console.log('Clicked:', item)}
/>

// Custom Link Component
// IMPORTANT: Always spread {...props} to preserve styling
// React Router example (uses 'to' instead of 'href')
import { Link as RouterLink } from 'react-router-dom';

const ReactRouterLink = ({
  href,
  children,
  ...props
}: React.PropsWithChildren<LinkComponentProps>) => {
  return (
    <RouterLink
      to={href}
      {...props} // Required to preserve NavList styles
    >
      {children}
    </RouterLink>
  );
};

<NavList items={items} LinkComponent={ReactRouterLink} />

Variants:

  • sidebar - Sidebar navigation with larger icons (20px) and generous spacing
  • menu - Card-based menu with hover animations (18px icons)
  • dropdown - Compact dropdown with subtle borders (16px icons)

Features:

  • Auto-grouping - Items automatically group by group property
  • Active states - Highlight active items with active prop
  • Disabled items - Prevent interaction with disabled prop
  • Dividers - Visual separators with divider prop on items or groups
  • Icon support - 200k+ icons via @ttoss/react-icons
  • Custom routing - Compatible with Next.js, React Router via LinkComponent

Theme-aware modals with accessibility features. 📖 Docs

import { Modal } from '@ttoss/components/Modal';

<Modal
  isOpen={isOpen}
  onRequestClose={() => setIsOpen(false)}
  style={{ content: { backgroundColor: 'secondary' } }}
>
  Modal content
</Modal>;

NotificationCard

Display notification messages with actions. 📖 Docs

import { NotificationCard } from '@ttoss/components/NotificationCard';

<NotificationCard
  title="Notification Title"
  message="Notification message"
  onClose={() => {}}
/>;

NotificationsMenu

Menu component for displaying notifications. 📖 Docs

import { NotificationsMenu } from '@ttoss/components/NotificationsMenu';

<NotificationsMenu
  notifications={[{ id: '1', title: 'New message', read: false }]}
  onNotificationClick={(notification) => {}}
/>;

Debounced search input with loading states. 📖 Docs

import { Search } from '@ttoss/components/Search';

<Search
  value={searchText}
  onChange={setSearchText}
  loading={isLoading}
  debounce={300}
/>;

Table

Flexible tables with sorting and pagination. Uses TanStack Table. 📖 Docs

import {
  Table,
  useReactTable,
  createColumnHelper,
} from '@ttoss/components/Table';

const columns = [
  columnHelper.accessor('name', { header: 'Name' }),
  columnHelper.accessor('email', { header: 'Email' }),
];

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
});

<Table>
  <Table.Head>
    {table.getHeaderGroups().map((headerGroup) => (
      <Table.Row key={headerGroup.id}>
        {headerGroup.headers.map((header) => (
          <Table.Header key={header.id}>
            {flexRender(header.column.columnDef.header, header.getContext())}
          </Table.Header>
        ))}
      </Table.Row>
    ))}
  </Table.Head>
  <Table.Body>
    {table.getRowModel().rows.map((row) => (
      <Table.Row key={row.id}>
        {row.getVisibleCells().map((cell) => (
          <Table.Cell key={cell.id}>
            {flexRender(cell.column.columnDef.cell, cell.getContext())}
          </Table.Cell>
        ))}
      </Table.Row>
    ))}
  </Table.Body>
</Table>;

Tabs

Tab navigation with content panels. 📖 Docs

import { Tabs } from '@ttoss/components/Tabs';

<Tabs>
  <Tabs.TabList>
    <Tabs.Tab>Tab 1</Tabs.Tab>
    <Tabs.Tab>Tab 2</Tabs.Tab>
  </Tabs.TabList>
  <Tabs.TabContent>
    <Tabs.TabPanel>Content 1</Tabs.TabPanel>
    <Tabs.TabPanel>Content 2</Tabs.TabPanel>
  </Tabs.TabContent>
</Tabs>;

Toast

Toast notification system. 📖 Docs

import { Toast } from '@ttoss/components/Toast';

<Toast
  message="Success message"
  type="success"
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
/>;