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

@ofi-summerai/markui

v0.1.13

Published

Mark UI component library — React + Tailwind CSS 4 + shadcn/ui

Downloads

1,520

Readme

@ofi-summerai/markui

npm version license react tailwind

Full documentation: github.com/OFI-Summer-AI/mark-ui

A production-ready React component library built on shadcn/ui and Radix UI, styled with Tailwind CSS 4. Ships 47 accessible UI primitives plus a suite of higher-level custom components for marketing and dashboard applications.


Installation

# npm
npm i @ofi-summerai/markui

# pnpm
pnpm add @ofi-summerai/markui

# yarn
yarn add @ofi-summerai/markui

Required peer dependencies

npm i lucide-react recharts react-markdown remark-gfm sonner

Optional (install only what you use):

npm i framer-motion          # ShineBorderButton
npm i react-router-dom       # BreadcrumbRouter, AppHeaderActions
npm i @tanstack/react-table  # DynamicTable
npm i react-day-picker date-fns  # Calendar / date picker
npm i cmdk embla-carousel-react input-otp vaul  # Other shadcn primitives

Set up styles with Tailwind CSS

Important: Follow these steps carefully to avoid a PostCSS build error.

The error you'll see if done wrong:

[plugin:vite:css] [postcss] @layer base is used but no matching @tailwind base directive is present.

This happens because markui's stylesheet uses Tailwind's @layer base internally. When imported from a .tsx file, PostCSS processes it in isolation — without the @tailwind base directive — and crashes.

Correct setup — add to src/index.css:

/* src/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@import '@ofi-summerai/markui/style.css';

The @import must come after the three @tailwind directives.

Do NOT import it in any .tsx or .ts file:

// Remove this from any component file
import '@ofi-summerai/markui/style.css'

| Import location | @tailwind base visible? | Result | |----------------|--------------------------|--------| | src/index.css | Yes | Builds correctly | | Any .tsx component | No | PostCSS crashes |

Vite processes CSS imported from component files in isolation. The @layer base directive inside markui/style.css requires @tailwind base to already be declared in the same processing context, which only exists in src/index.css.


Quick Start

import { Button } from '@ofi-summerai/markui/primitives'
import { KPICard } from '@ofi-summerai/markui/components'
import { TrendingUp } from 'lucide-react'

export default function Dashboard() {
  return (
    <div className="p-6 space-y-4">
      <div className="grid grid-cols-3 gap-4">
        <KPICard
          title="Total Reach"
          value="124,500"
          trend={12.4}
          trendLabel="vs last month"
          icon={<TrendingUp size={18} />}
        />
        <KPICard
          title="Engagement Rate"
          value="4.8%"
          trend={-1.2}
          trendLabel="vs last week"
        />
        <KPICard
          title="Posts Published"
          value={38}
          trend={5.0}
          trendLabel="this month"
        />
      </div>

      <div className="flex gap-2">
        <Button>Create Post</Button>
        <Button variant="outline">View Analytics</Button>
        <Button variant="ghost">Settings</Button>
      </div>
    </div>
  )
}

Component Overview

@ofi-summerai/markui — Charts Props Reference

Available Chart Components

| Component | Export Name | |---|---| | Bar Chart | BarChartComponent | | Line Chart | LineChartComponent | | Pie Chart | PieChartComponent |


BarChartComponent

Import

import { BarChartComponent } from "@ofi-summerai/markui";

Props

| Prop | Type | Required | Description | |---|---|---|---| | data | Record<string, unknown>[] | ✅ | Array of data objects | | dataKeys | string[] | ✅ | Fields in data to render as bars | | xKey | string | ✅ | Field in data to use as the X axis | | title | string | ❌ | Card title shown above the chart | | description | string | ❌ | Subtitle shown below the title | | className | string | ❌ | Additional CSS classes |

Single Bar Example

<BarChartComponent
  data={[
    { month: "Jan", revenue: 10 },
    { month: "Feb", revenue: 20 },
    { month: "Mar", revenue: 15 },
  ]}
  dataKeys={["revenue"]}
  xKey="month"
  title="Monthly Revenue"
/>

Multiple Bars Example

<BarChartComponent
  data={[
    { month: "Jan", revenue: 10, expenses: 6 },
    { month: "Feb", revenue: 20, expenses: 12 },
    { month: "Mar", revenue: 15, expenses: 9 },
  ]}
  dataKeys={["revenue", "expenses"]}
  xKey="month"
  title="Revenue vs Expenses"
  description="Monthly comparison"
/>

When dataKeys has more than one entry, a legend is automatically rendered.


LineChartComponent

Import

import { LineChartComponent } from "@ofi-summerai/markui";

Run cat ../mark-ui/src/components/charts/LineChart.tsx to confirm props.


PieChartComponent

Import

import { PieChartComponent } from "@ofi-summerai/markui";

Run cat ../mark-ui/src/components/charts/PieChart.tsx to confirm props.


Chart Colors

Colors are applied automatically in this order:

| Index | Hex | Preview | |---|---|---| | 0 | #CCA23E | Golden amber (primary) | | 1 | #000000 | Black | | 2 | #FFFFFF | White | | 3 | #A07C28 | Amber dark | | 4 | #333333 | Soft black | | 5 | #E8D5A3 | Light amber |

Colors cycle back from index 0 if there are more than 6 dataKeys.


Common Errors

| Error | Cause | Fix | |---|---|---| | does not provide an export named 'BarChart' | Wrong import name | Use BarChartComponent not BarChart | | Chart renders empty | Wrong xKey or dataKeys | Make sure keys match your data object fields exactly | | No bars visible | data is empty or undefined | Check your data source before passing to the component |

Primitives (shadcn/ui)

| Component | Description | |-----------|-------------| | Accordion | Vertically stacked expandable sections | | Alert | Contextual feedback banners (info, warning, error) | | AlertDialog | Modal dialog requiring user confirmation before an action | | Avatar | Circular user/brand image with initials fallback | | Badge | Small status or label indicator | | Breadcrumb | Hierarchical page location trail | | Button | Versatile action trigger with multiple variants and sizes | | Calendar | Date picker calendar grid (uses react-day-picker) | | Card | Contained surface for grouping related content | | Carousel | Horizontally scrollable slide container (Embla) | | Chart | Recharts-based chart container with built-in theming | | Checkbox | Binary toggle input with indeterminate state support | | Collapsible | Single section expand/collapse without animation overhead | | Command | Accessible command palette / combobox (cmdk) | | Dialog | Modal overlay dialog | | Drawer | Slide-in panel from screen edge (vaul) | | DropdownMenu | Floating action menu anchored to a trigger | | Empty | Placeholder for empty states | | Field | Form field wrapper combining Label + Input + error message | | Form | React Hook Form integration with validation messages | | HoverCard | Rich preview card revealed on hover | | Input | Single-line text input | | InputGroup | Input with leading/trailing add-ons | | InputOtp | One-time password segmented input (input-otp) | | Label | Accessible form label | | NavigationMenu | Top-level site navigation with dropdown support | | Pagination | Page number navigation control | | Popover | Non-modal floating content panel | | Portal | Renders children into a portal outside the DOM tree | | Progress | Linear progress bar | | ScrollArea | Custom-styled scrollable region | | Select | Single-value dropdown selector | | Separator | Horizontal or vertical divider line | | Sheet | Slide-in side panel (Dialog variant) | | Sidebar | Collapsible application sidebar with nested nav support | | Skeleton | Animated loading placeholder shape | | Slider | Range or value slider input | | Sonner | Toast notification system (Sonner/Toaster) | | Switch | Binary toggle switch | | Table | Accessible HTML table with styled rows and cells | | Tabs | Tabbed content panels | | Textarea | Multi-line text input | | Toggle | Single pressable button that retains active state | | ToggleGroup | Group of mutually-exclusive or multi-select toggles | | Tooltip | Short text hint revealed on hover/focus | | CountrySelector | Flag + country name selector with search |

Custom Components

| Component | Description | |-----------|-------------| | BrandLogo | Displays a brand image with automatic initials fallback | | ErrorState | Full-area error display with optional retry button | | LoadingState | Centered spinning loader for async content | | ShineBorderButton | Button with animated gradient border (requires framer-motion) | | TooltipHover | Enriched tooltip with title, body text, and optional action | | KPICard | Metric card with value, trend indicator, and icon slot | | FacebookIcon | Facebook SVG icon | | InstagramIcon | Instagram SVG icon | | LinkedInIcon | LinkedIn SVG icon | | TikTokIcon | TikTok SVG icon | | DynamicTable | Full-featured data table with sorting, filtering, and pagination | | AvatarDropdown | User avatar that opens a profile/sign-out dropdown | | BreadcrumbRouter | Auto-generated breadcrumbs from the current react-router path | | AppHeaderActions | Header action bar rendering router links, links, buttons, or custom nodes | | EditImageModal | AI image editing modal with upload, prompt, and preview | | ChatInput | Chat message input with send button and keyboard shortcut | | ChatMessage | Single rendered chat message bubble (user or assistant) | | ChatMessagesList | Scrollable list of ChatMessage components | | TypingIndicator | Animated three-dot typing indicator |


Exports

The library offers three entry points:

// Full library — all primitives + custom components
import { Button, KPICard, DynamicTable } from '@ofi-summerai/markui'

// Only shadcn/ui primitives
import { Button, Card } from '@ofi-summerai/markui/primitives'

// Only custom components
import { KPICard } from '@ofi-summerai/markui/components'

Stylesheet: Add @import '@ofi-summerai/markui/style.css' to your src/index.css — see Set up styles with Tailwind CSS above.


Theming

The library uses CSS custom properties for all design tokens. Override them in your global stylesheet after importing the stylesheet:

/* your-app/globals.css */
:root {
  --primary: #6366f1;
  --on-primary: #ffffff;
  --primary-container: #e0e7ff;
  --secondary: #0f172a;
  --background: #ffffff;
  --surface: #f8fafc;
  --radius: 0.5rem;
}

Key CSS Variables

| Variable | Default (light) | Purpose | |----------|----------------|---------| | --primary | #D946EF | Brand accent color | | --secondary | #0b3948 | Secondary brand color | | --background | #fcfcfb | Page background | | --surface | #fcfcfb | Card/panel surface | | --on-surface | #333231 | Text on surface | | --outline | #a39a8e | Border color | | --outline-variant | #ebe6e0 | Subtle border color | | --muted | #f4f4f5 | Muted background | | --muted-foreground | #71717a | Muted text | | --radius | 0.625rem | Base border radius | | --error | #b3261e | Error/destructive color | | --success | #4ac087 | Success color |

Chart-specific variables --chart-1 through --chart-10 control the default palette used by the Chart primitive.


Dark Mode

Add the .dark class to your <html> element to activate the dark theme:

// Toggle dark mode
document.documentElement.classList.toggle('dark')

Both .dark and [data-theme="dark"] selectors are supported:

<html class="dark">
<!-- or -->
<html data-theme="dark">

Requirements

  • React >= 18.2
  • Node >= 18

Documentation

Full per-component documentation lives on GitHub: