Files
sigpro-ui/docs/components/stat.md
2026-03-31 23:41:51 +02:00

19 KiB

Stat

Statistic card component for displaying metrics, counts, and key performance indicators with optional icons and descriptions.

Tag

Stat

Props

Prop Type Default Description
label string | VNode | Signal - Statistic label/title
value string | number | Signal - Main statistic value
desc string | VNode | Signal - Description or trend text
icon string | VNode | Signal - Icon displayed in the figure area
class string '' Additional CSS classes (DaisyUI + Tailwind)

Live Examples

Basic Stat

Live Demo

const BasicDemo = () => {
  return Div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [
    Stat({
      label: 'Total Users',
      value: '2,345',
      desc: '↗︎ 120 new users this month'
    }),
    Stat({
      label: 'Revenue',
      value: '$45,678',
      desc: '↘︎ 5% decrease from last month'
    }),
    Stat({
      label: 'Conversion Rate',
      value: '3.45%',
      desc: '↗︎ 0.5% increase'
    })
  ]);
};
$mount(BasicDemo, '#demo-basic');

With Icons

Live Demo

const IconsDemo = () => {
  return Div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [
    Stat({
      label: 'Active Users',
      value: '1,234',
      desc: 'Currently online',
      icon: Icons.iconShow
    }),
    Stat({
      label: 'New Orders',
      value: '89',
      desc: 'Today',
      icon: Icons.iconSuccess
    }),
    Stat({
      label: 'Pending Tasks',
      value: '23',
      desc: 'Need attention',
      icon: Icons.iconWarning
    })
  ]);
};
$mount(IconsDemo, '#demo-icons');

Reactive Values

Live Demo

const ReactiveDemo = () => {
  const count = $(0);
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, [
      Stat({
        label: 'Counter',
        value: () => count(),
        desc: 'Click the button to increase',
        icon: Icons.iconInfo
      }),
      Stat({
        label: 'Squared',
        value: () => Math.pow(count(), 2),
        desc: 'Square of counter',
        icon: Icons.iconSuccess
      })
    ]),
    Div({ class: 'flex gap-2 justify-center' }, [
      Button({ 
        class: 'btn btn-primary',
        onclick: () => count(count() + 1)
      }, 'Increment'),
      Button({ 
        class: 'btn btn-ghost',
        onclick: () => count(0)
      }, 'Reset')
    ])
  ]);
};
$mount(ReactiveDemo, '#demo-reactive');

With Trend Indicators

Live Demo

const TrendsDemo = () => {
  return Div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [
    Stat({
      label: 'Weekly Sales',
      value: '$12,345',
      desc: Div({ class: 'text-success' }, '↗︎ 15% increase'),
      icon: Icons.iconSuccess
    }),
    Stat({
      label: 'Bounce Rate',
      value: '42%',
      desc: Div({ class: 'text-error' }, '↘︎ 3% from last week'),
      icon: Icons.iconError
    }),
    Stat({
      label: 'Avg. Session',
      value: '4m 32s',
      desc: Div({ class: 'text-warning' }, '↗︎ 12 seconds'),
      icon: Icons.iconWarning
    })
  ]);
};
$mount(TrendsDemo, '#demo-trends');

Multiple Stats in Row

Live Demo

const MultipleDemo = () => {
  return Div({ class: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, [
    Stat({
      label: 'Posts',
      value: '1,234',
      desc: 'Total content',
      icon: Span({ class: 'text-2xl' }, '📝')
    }),
    Stat({
      label: 'Comments',
      value: '8,901',
      desc: 'Engagement',
      icon: Span({ class: 'text-2xl' }, '💬')
    }),
    Stat({
      label: 'Likes',
      value: '12,345',
      desc: 'Reactions',
      icon: Span({ class: 'text-2xl' }, '❤️')
    }),
    Stat({
      label: 'Shares',
      value: '456',
      desc: 'Viral reach',
      icon: Span({ class: 'text-2xl' }, '🔄')
    })
  ]);
};
$mount(MultipleDemo, '#demo-multiple');

Dashboard Example

Live Demo

const DashboardDemo = () => {
  const stats = $({
    users: 1245,
    revenue: 89342,
    orders: 342,
    satisfaction: 94
  });
  
  const updateStats = () => {
    stats({
      users: stats().users + Math.floor(Math.random() * 50),
      revenue: stats().revenue + Math.floor(Math.random() * 1000),
      orders: stats().orders + Math.floor(Math.random() * 20),
      satisfaction: Math.min(100, stats().satisfaction + Math.floor(Math.random() * 5) - 2)
    });
  };
  
  return Div({ class: 'flex flex-col gap-6' }, [
    Div({ class: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, [
      Stat({
        label: 'Total Users',
        value: () => stats().users.toLocaleString(),
        desc: 'Registered users',
        icon: Icons.iconShow
      }),
      Stat({
        label: 'Revenue',
        value: () => `$${stats().revenue.toLocaleString()}`,
        desc: 'This month',
        icon: Icons.iconSuccess
      }),
      Stat({
        label: 'Orders',
        value: () => stats().orders.toLocaleString(),
        desc: 'Completed',
        icon: Icons.iconInfo
      }),
      Stat({
        label: 'Satisfaction',
        value: () => `${stats().satisfaction}%`,
        desc: stats().satisfaction > 90 ? 'Excellent!' : 'Good',
        icon: Icons.iconWarning
      })
    ]),
    Div({ class: 'flex justify-center' }, [
      Button({ 
        class: 'btn btn-primary',
        onclick: updateStats
      }, 'Refresh Data')
    ])
  ]);
};
$mount(DashboardDemo, '#demo-dashboard');

All Variants

Live Demo

const VariantsDemo = () => {
  return Div({ class: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, [
    Stat({
      label: 'Primary Stat',
      value: '1,234',
      desc: 'With description',
      icon: Icons.iconInfo,
      class: 'bg-primary/10 text-primary'
    }),
    Stat({
      label: 'Success Stat',
      value: '89%',
      desc: 'Success rate',
      icon: Icons.iconSuccess,
      class: 'bg-success/10 text-success'
    }),
    Stat({
      label: 'Warning Stat',
      value: '23',
      desc: 'Pending items',
      icon: Icons.iconWarning,
      class: 'bg-warning/10 text-warning'
    }),
    Stat({
      label: 'Error Stat',
      value: '5',
      desc: 'Failed attempts',
      icon: Icons.iconError,
      class: 'bg-error/10 text-error'
    })
  ]);
};
$mount(VariantsDemo, '#demo-variants');

Compact Stats

Live Demo

const CompactDemo = () => {
  return Div({ class: 'flex flex-wrap gap-4' }, [
    Stat({
      label: 'Views',
      value: '12.3K',
      class: 'stat-compact'
    }),
    Stat({
      label: 'Likes',
      value: '2,456',
      class: 'stat-compact'
    }),
    Stat({
      label: 'Comments',
      value: '345',
      class: 'stat-compact'
    }),
    Stat({
      label: 'Shares',
      value: '89',
      class: 'stat-compact'
    })
  ]);
};
$mount(CompactDemo, '#demo-compact');
<script> (function() { const initStatExamples = () => { // 1. Basic Stat const basicTarget = document.querySelector('#demo-basic'); if (basicTarget && !basicTarget.hasChildNodes()) { const BasicDemo = () => { return Div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [ Stat({ label: 'Total Users', value: '2,345', desc: '↗︎ 120 new users this month' }), Stat({ label: 'Revenue', value: '$45,678', desc: '↘︎ 5% decrease from last month' }), Stat({ label: 'Conversion Rate', value: '3.45%', desc: '↗︎ 0.5% increase' }) ]); }; $mount(BasicDemo, basicTarget); } // 2. With Icons const iconsTarget = document.querySelector('#demo-icons'); if (iconsTarget && !iconsTarget.hasChildNodes()) { const IconsDemo = () => { return Div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [ Stat({ label: 'Active Users', value: '1,234', desc: 'Currently online', icon: Icons.iconShow }), Stat({ label: 'New Orders', value: '89', desc: 'Today', icon: Icons.iconSuccess }), Stat({ label: 'Pending Tasks', value: '23', desc: 'Need attention', icon: Icons.iconWarning }) ]); }; $mount(IconsDemo, iconsTarget); } // 3. Reactive Values const reactiveTarget = document.querySelector('#demo-reactive'); if (reactiveTarget && !reactiveTarget.hasChildNodes()) { const ReactiveDemo = () => { const count = $(0); return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, [ Stat({ label: 'Counter', value: () => count(), desc: 'Click the button to increase', icon: Icons.iconInfo }), Stat({ label: 'Squared', value: () => Math.pow(count(), 2), desc: 'Square of counter', icon: Icons.iconSuccess }) ]), Div({ class: 'flex gap-2 justify-center' }, [ Button({ class: 'btn btn-primary', onclick: () => count(count() + 1) }, 'Increment'), Button({ class: 'btn btn-ghost', onclick: () => count(0) }, 'Reset') ]) ]); }; $mount(ReactiveDemo, reactiveTarget); } // 4. With Trend Indicators const trendsTarget = document.querySelector('#demo-trends'); if (trendsTarget && !trendsTarget.hasChildNodes()) { const TrendsDemo = () => { return Div({ class: 'grid grid-cols-1 md:grid-cols-3 gap-4' }, [ Stat({ label: 'Weekly Sales', value: '$12,345', desc: Div({ class: 'text-success' }, '↗︎ 15% increase'), icon: Icons.iconSuccess }), Stat({ label: 'Bounce Rate', value: '42%', desc: Div({ class: 'text-error' }, '↘︎ 3% from last week'), icon: Icons.iconError }), Stat({ label: 'Avg. Session', value: '4m 32s', desc: Div({ class: 'text-warning' }, '↗︎ 12 seconds'), icon: Icons.iconWarning }) ]); }; $mount(TrendsDemo, trendsTarget); } // 5. Multiple Stats in Row const multipleTarget = document.querySelector('#demo-multiple'); if (multipleTarget && !multipleTarget.hasChildNodes()) { const MultipleDemo = () => { return Div({ class: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, [ Stat({ label: 'Posts', value: '1,234', desc: 'Total content', icon: Span({ class: 'text-2xl' }, '📝') }), Stat({ label: 'Comments', value: '8,901', desc: 'Engagement', icon: Span({ class: 'text-2xl' }, '💬') }), Stat({ label: 'Likes', value: '12,345', desc: 'Reactions', icon: Span({ class: 'text-2xl' }, '❤️') }), Stat({ label: 'Shares', value: '456', desc: 'Viral reach', icon: Span({ class: 'text-2xl' }, '🔄') }) ]); }; $mount(MultipleDemo, multipleTarget); } // 6. Dashboard Example const dashboardTarget = document.querySelector('#demo-dashboard'); if (dashboardTarget && !dashboardTarget.hasChildNodes()) { const DashboardDemo = () => { const stats = $({ users: 1245, revenue: 89342, orders: 342, satisfaction: 94 }); const updateStats = () => { stats({ users: stats().users + Math.floor(Math.random() * 50), revenue: stats().revenue + Math.floor(Math.random() * 1000), orders: stats().orders + Math.floor(Math.random() * 20), satisfaction: Math.min(100, stats().satisfaction + Math.floor(Math.random() * 5) - 2) }); }; return Div({ class: 'flex flex-col gap-6' }, [ Div({ class: 'grid grid-cols-1 md:grid-cols-4 gap-4' }, [ Stat({ label: 'Total Users', value: () => stats().users.toLocaleString(), desc: 'Registered users', icon: Icons.iconShow }), Stat({ label: 'Revenue', value: () => `$${stats().revenue.toLocaleString()}`, desc: 'This month', icon: Icons.iconSuccess }), Stat({ label: 'Orders', value: () => stats().orders.toLocaleString(), desc: 'Completed', icon: Icons.iconInfo }), Stat({ label: 'Satisfaction', value: () => `${stats().satisfaction}%`, desc: stats().satisfaction > 90 ? 'Excellent!' : 'Good', icon: Icons.iconWarning }) ]), Div({ class: 'flex justify-center' }, [ Button({ class: 'btn btn-primary', onclick: updateStats }, 'Refresh Data') ]) ]); }; $mount(DashboardDemo, dashboardTarget); } // 7. All Variants const variantsTarget = document.querySelector('#demo-variants'); if (variantsTarget && !variantsTarget.hasChildNodes()) { const VariantsDemo = () => { return Div({ class: 'grid grid-cols-1 md:grid-cols-2 gap-4' }, [ Stat({ label: 'Primary Stat', value: '1,234', desc: 'With description', icon: Icons.iconInfo, class: 'bg-primary/10 text-primary' }), Stat({ label: 'Success Stat', value: '89%', desc: 'Success rate', icon: Icons.iconSuccess, class: 'bg-success/10 text-success' }), Stat({ label: 'Warning Stat', value: '23', desc: 'Pending items', icon: Icons.iconWarning, class: 'bg-warning/10 text-warning' }), Stat({ label: 'Error Stat', value: '5', desc: 'Failed attempts', icon: Icons.iconError, class: 'bg-error/10 text-error' }) ]); }; $mount(VariantsDemo, variantsTarget); } // 8. Compact Stats const compactTarget = document.querySelector('#demo-compact'); if (compactTarget && !compactTarget.hasChildNodes()) { const CompactDemo = () => { return Div({ class: 'flex flex-wrap gap-4' }, [ Stat({ label: 'Views', value: '12.3K', class: 'stat-compact' }), Stat({ label: 'Likes', value: '2,456', class: 'stat-compact' }), Stat({ label: 'Comments', value: '345', class: 'stat-compact' }), Stat({ label: 'Shares', value: '89', class: 'stat-compact' }) ]); }; $mount(CompactDemo, compactTarget); } }; initStatExamples(); if (window.$docsify) { window.$docsify.plugins = [].concat(window.$docsify.plugins || [], (hook) => { hook.doneEach(initStatExamples); }); } })(); </script>