npm.io
1.6.5 • Published 7h ago

design-system-eduno

Licence
Version
1.6.5
Deps
38
Size
1.4 MB
Vulns
0
Weekly
0

Design System Eduno

A modern React component library built with TypeScript, Tailwind CSS, and Radix UI. Provides a comprehensive set of customizable and accessible UI components with dynamic theming support.

Installation

From npm (Production)

pnpm add design-system-eduno
# or
npm install design-system-eduno
# or
yarn add design-system-eduno
Local Development

For local development without publishing a new version, see Local Development Linking.

Usage

Basic Setup
import { Button, ThemeProvider } from 'design-system-eduno';

function App() {
  return (
    <ThemeProvider theme={{ primaryColor: "#023047" }}>
      <Button variant="default">Click me</Button>
    </ThemeProvider>
  );
}
Theme Configuration

The library includes a dynamic theming system that accepts hex color values:

<ThemeProvider
  theme={{
    primaryColor: "#023047",
    secondaryColor: "#fb8500"
  }}
>
  {/* Your app */}
</ThemeProvider>
Available Components
  • Form Components: Button, Input, Label, Checkbox, Select, Switch, DatePicker
  • Data Display: DataTable, Badge, Avatar, Typography, Card
  • Layout: Sidebar, Stepper, FormContainer, ScrollArea
  • Feedback: Dialog, Tooltip, PageLoader, Skeleton, ErrorField
  • Navigation: Command, DropdownMenu, Collapsible, Popover
  • Other: Calendar, ProfileImage, Searchbar

Development

Prerequisites
  • Node.js 18+
  • pnpm (recommended)
Setup
# Install dependencies
pnpm install

# Start development server
pnpm dev

# Start Storybook (component documentation)
pnpm storybook
Build
# Build the library
pnpm build

# Build in watch mode (for local development)
pnpm build:watch

# Build Storybook
pnpm build-storybook
Linting
pnpm lint

Local Development Linking

To use this design system in another project locally without publishing:

In this design system repository:

pnpm build
pnpm link --global

In your consuming project:

pnpm link --global design-system-eduno

For active development (auto-rebuild on changes):

# In design system repo - run in a separate terminal
pnpm build:watch

To unlink:

# In consuming project
pnpm unlink design-system-eduno

# In design system repo (optional)
pnpm unlink --global
Option 2: Direct File Path

In your consuming project's package.json:

{
  "dependencies": {
    "design-system-eduno": "file:../path/to/eduno-design-system"
  }
}

Then run pnpm install. Remember to run pnpm build in the design system whenever you make changes.

Option 3: pnpm workspace (for monorepos)
{
  "dependencies": {
    "design-system-eduno": "workspace:*"
  }
}

Component Examples

Button
import { Button } from 'design-system-eduno';

<Button variant="default" size="lg">Primary Button</Button>
<Button variant="outline">Outline Button</Button>
<Button variant="destructive">Delete</Button>
<Button isLoading>Loading...</Button>
DataTable
import { DataTable } from 'design-system-eduno';

<DataTable
  data={users}
  columns={columns}
  configuration={{
    pagination: {
      currentPage: 1,
      rowsPerPage: 10,
      total: 100,
      onChangePage: (page) => console.log(page),
      onChangeRows: (rows) => console.log(rows),
    },
    search: {
      query: searchQuery,
      onSearch: (value) => setSearchQuery(value),
      onClearSearch: () => setSearchQuery(''),
    },
  }}
  filterMode="server" // or "client"
  density="default" // "compact" (36px rows) | "default" (44px) | "comfortable" (52px)
  emptyState={{
    title: 'Todavía no hay clientes',
    description: 'Cuando agregues el primero va a aparecer acá.',
    action: <Button size="sm">Agregar cliente</Button>,
  }}
/>

Per-column layout lives in meta, so the header and its cells always agree:

const columns: TColumnDef<IUser>[] = [
  // Keeps the identity column in view while the table scrolls sideways
  { id: 'name', header: 'Nombre', meta: { pinned: 'left' }, minSize: 220, cell },
  // Right-aligned and tabular: digits line up by place value and never shift
  { id: 'total', header: 'Total', meta: { numeric: true }, cell },
  { id: 'status', header: 'Estado', meta: { align: 'center' }, cell },
  // `headerLabel` is what the column menu and the sort announcement read
  { id: 'actions', header: 'Acciones', meta: { align: 'right', headerLabel: 'Acciones' }, cell },
];

tableHeight is a max-h-* class: the surface shrinks to its rows on a short page and scrolls under a sticky header on a long one. The empty state tells "nothing here yet" apart from "nothing matched", and only the first case needs emptyState — the second one offers to clear the search on its own.

Design decisions baked in:

  • The search and the columns menu sit above the surface with real air between them and the table. Tucked inside, the field looked welded to the column titles.
  • Header and footer share a tinted rail (.ed-dt-rail), so the data sits between two edges. A header floating on the same surface as the rows reads as unfinished.
  • Column titles are 12px / 500 / uppercase with 0.025em tracking — the label signal, calibrated: 11px reads cheap and double the tracking over-spaces.
  • Row height lives on the cell, so a 32px action trigger doesn't quietly decide the density. The default is 52px because these tables are read a row at a time to decide something; 36-44px is for auditing hundreds of rows.
  • The footer spends the minimum chrome: the range, a rows-per-page menu, and prev/next only when there is more than one page. First/last are gone — four arrows for a two-arrow job.
  • Only the sorted column shows a solid arrow; idle columns keep a faint one so touch users still see the affordance.
Dialog
import { Dialog } from 'design-system-eduno';

<Dialog
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
  title="Dialog Title"
  description="Dialog description"
  size="md"
>
  {/* Dialog content */}
</Dialog>

Component Structure

All components must follow this folder structure:

ComponentName/
├── index.ts                    # Exports component and types
├── ComponentName.tsx           # Main component implementation
├── types/
│   └── index.ts                # TypeScript interfaces and types
├── constants/
│   └── index.ts                # Constants (if needed)
├── components/                 # Subcomponents (if needed)
│   └── SubComponent/
│       ├── index.ts
│       ├── SubComponent.tsx
│       └── types/
│           └── index.ts
├── storybook/
│   └── ComponentName.stories.tsx
└── tests/                      # Tests (if needed)
    └── ComponentName.test.tsx
Structure Guidelines
  • index.ts: Always export the component and its types
  • ComponentName.tsx: Main component using React.forwardRef when wrapping DOM elements
  • types/index.ts: All TypeScript interfaces and types for the component
  • constants/index.ts: Only if the component requires constants
  • components/: Subcomponents follow the same structure recursively
  • storybook/: Storybook stories in their own folder
  • tests/: Test files in their own folder

Technology Stack

  • React 19 - UI library
  • TypeScript - Type safety
  • Tailwind CSS - Utility-first styling
  • Radix UI - Accessible component primitives
  • Vite - Build tool
  • Storybook - Component documentation
  • class-variance-authority - Variant management
  • TanStack Table - Powerful tables
  • React Aria Components - Accessible interactions
  • Framer Motion - Animations

Publishing

To publish a new version:

# Build the library
pnpm build

# Update version in package.json
npm version patch # or minor, major

# Publish to npm (requires npm login)
npm publish

Requirements

  • React: ^19.0.0 (peer dependency)
  • React DOM: ^19.0.0 (peer dependency)
  • Node.js: 18+

License

[Add your license here]

Contributing

[Add contributing guidelines here]