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

20 KiB

Timeline

Timeline component for displaying chronological events, steps, or progress with customizable icons and content.

Tag

Timeline

Props

Prop Type Default Description
items Array<TimelineItem> | Signal [] Timeline items to display
vertical boolean | Signal<boolean> true Vertical or horizontal orientation
compact boolean | Signal<boolean> false Compact mode with less padding
class string '' Additional CSS classes (DaisyUI + Tailwind)

TimelineItem Structure

Property Type Description
title string | VNode | Signal Event title or main text
detail string | VNode | Signal Additional details or description
icon string | VNode Custom icon (overrides type)
type string Type: 'success', 'warning', 'error', 'info'
completed boolean Whether event is completed (affects connector)

Live Examples

Basic Timeline

Live Demo

const BasicDemo = () => {
  const events = [
    { title: 'Project Started', detail: 'Initial planning and setup', type: 'info', completed: true },
    { title: 'Design Phase', detail: 'UI/UX design completed', type: 'success', completed: true },
    { title: 'Development', detail: 'Core features implemented', type: 'warning', completed: false },
    { title: 'Testing', detail: 'Quality assurance', type: 'info', completed: false },
    { title: 'Launch', detail: 'Production deployment', type: 'success', completed: false }
  ];
  
  return Timeline({ items: events });
};
$mount(BasicDemo, '#demo-basic');

Horizontal Timeline

Live Demo

const HorizontalDemo = () => {
  const steps = [
    { title: 'Step 1', detail: 'Requirements', type: 'success', completed: true },
    { title: 'Step 2', detail: 'Design', type: 'success', completed: true },
    { title: 'Step 3', detail: 'Development', type: 'warning', completed: false },
    { title: 'Step 4', detail: 'Testing', type: 'info', completed: false },
    { title: 'Step 5', detail: 'Deploy', type: 'info', completed: false }
  ];
  
  return Timeline({ 
    items: steps, 
    vertical: false,
    class: 'min-w-[600px]'
  });
};
$mount(HorizontalDemo, '#demo-horizontal');

Compact Timeline

Live Demo

const CompactDemo = () => {
  const activities = [
    { title: 'User login', detail: '10:30 AM', type: 'success', completed: true },
    { title: 'Viewed dashboard', detail: '10:32 AM', type: 'info', completed: true },
    { title: 'Updated profile', detail: '10:45 AM', type: 'success', completed: true },
    { title: 'Made purchase', detail: '11:00 AM', type: 'warning', completed: false }
  ];
  
  return Timeline({ 
    items: activities, 
    compact: true 
  });
};
$mount(CompactDemo, '#demo-compact');

Custom Icons

Live Demo

const IconsDemo = () => {
  const milestones = [
    { title: 'Kickoff', detail: 'Project kickoff meeting', icon: Icons.iconInfo, completed: true },
    { title: 'MVP', detail: 'Minimum viable product', icon: Icons.iconSuccess, completed: true },
    { title: 'Beta', detail: 'Beta release', icon: Icons.iconWarning, completed: false },
    { title: 'Launch', detail: 'Public launch', icon: Icons.iconShow, completed: false }
  ];
  
  return Timeline({ items: milestones });
};
$mount(IconsDemo, '#demo-icons');

Reactive Timeline

Live Demo

const ReactiveDemo = () => {
  const currentStep = $(2);
  const steps = [
    { title: 'Order Placed', detail: 'Your order has been confirmed', type: 'success', completed: true },
    { title: 'Processing', detail: 'Payment verified, preparing shipment', type: 'success', completed: currentStep() > 1 },
    { title: 'Shipped', detail: 'Package on the way', type: 'warning', completed: currentStep() > 2 },
    { title: 'Delivered', detail: 'Arriving soon', type: 'info', completed: currentStep() > 3 }
  ];
  
  const items = () => steps.map((step, idx) => ({
    ...step,
    completed: idx < currentStep()
  }));
  
  const nextStep = () => {
    if (currentStep() < steps.length) {
      currentStep(currentStep() + 1);
      Toast(`Step ${currentStep()}: ${steps[currentStep() - 1].title}`, 'alert-info', 1500);
    }
  };
  
  const reset = () => {
    currentStep(0);
    Toast('Order tracking reset', 'alert-warning', 1500);
  };
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Timeline({ items: items }),
    Div({ class: 'flex gap-2 justify-center mt-4' }, [
      Button({ 
        class: 'btn btn-primary btn-sm',
        onclick: nextStep,
        disabled: () => currentStep() >= steps.length
      }, 'Next Step'),
      Button({ 
        class: 'btn btn-ghost btn-sm',
        onclick: reset
      }, 'Reset')
    ])
  ]);
};
$mount(ReactiveDemo, '#demo-reactive');

Order Status Tracker

Live Demo

const OrderDemo = () => {
  const status = $('shipped');
  
  const statusMap = {
    pending: { title: 'Order Pending', detail: 'Awaiting confirmation', completed: false, type: 'warning' },
    confirmed: { title: 'Order Confirmed', detail: 'Payment received', completed: false, type: 'info' },
    processing: { title: 'Processing', detail: 'Preparing your order', completed: false, type: 'info' },
    shipped: { title: 'Shipped', detail: 'Package in transit', completed: false, type: 'info' },
    delivered: { title: 'Delivered', detail: 'Order completed', completed: false, type: 'success' }
  };
  
  const statusOrder = ['pending', 'confirmed', 'processing', 'shipped', 'delivered'];
  const currentIndex = statusOrder.indexOf(status());
  
  const items = statusOrder.map((key, idx) => ({
    ...statusMap[key],
    completed: idx < currentIndex
  }));
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Timeline({ items, compact: true }),
    Div({ class: 'flex gap-2 justify-center flex-wrap mt-4' }, statusOrder.map(s => 
      Button({ 
        class: `btn btn-xs ${status() === s ? 'btn-primary' : 'btn-ghost'}`,
        onclick: () => status(s)
      }, statusMap[s].title)
    ))
  ]);
};
$mount(OrderDemo, '#demo-order');

Company History

Live Demo

const HistoryDemo = () => {
  const milestones = [
    { 
      title: '2015 - Founded', 
      detail: 'Company started with 3 employees in a small office',
      type: 'success',
      completed: true
    },
    { 
      title: '2017 - First Product', 
      detail: 'Launched our first software product to market',
      type: 'success',
      completed: true
    },
    { 
      title: '2019 - Series A', 
      detail: 'Raised $5M in funding, expanded team to 50',
      type: 'success',
      completed: true
    },
    { 
      title: '2022 - Global Expansion', 
      detail: 'Opened offices in Europe and Asia',
      type: 'info',
      completed: true
    },
    { 
      title: '2024 - AI Integration', 
      detail: 'Launched AI-powered features',
      type: 'warning',
      completed: false
    },
    { 
      title: '2026 - Future Goals', 
      detail: 'Aiming for market leadership',
      type: 'info',
      completed: false
    }
  ];
  
  return Timeline({ items: milestones });
};
$mount(HistoryDemo, '#demo-history');

All Variants

Live Demo

const VariantsDemo = () => {
  const sampleItems = [
    { title: 'Event 1', detail: 'Description here', type: 'success', completed: true },
    { title: 'Event 2', detail: 'Description here', type: 'warning', completed: false },
    { title: 'Event 3', detail: 'Description here', type: 'info', completed: false }
  ];
  
  return Div({ class: 'flex flex-col gap-8' }, [
    Div({ class: 'text-sm font-bold' }, 'Vertical Timeline'),
    Timeline({ items: sampleItems }),
    
    Div({ class: 'text-sm font-bold mt-4' }, 'Horizontal Timeline'),
    Timeline({ items: sampleItems, vertical: false, class: 'min-w-[500px]' }),
    
    Div({ class: 'text-sm font-bold mt-4' }, 'Compact Timeline'),
    Timeline({ items: sampleItems, compact: true })
  ]);
};
$mount(VariantsDemo, '#demo-variants');
<script> (function() { const initTimelineExamples = () => { // 1. Basic Timeline const basicTarget = document.querySelector('#demo-basic'); if (basicTarget && !basicTarget.hasChildNodes()) { const BasicDemo = () => { const events = [ { title: 'Project Started', detail: 'Initial planning and setup', type: 'info', completed: true }, { title: 'Design Phase', detail: 'UI/UX design completed', type: 'success', completed: true }, { title: 'Development', detail: 'Core features implemented', type: 'warning', completed: false }, { title: 'Testing', detail: 'Quality assurance', type: 'info', completed: false }, { title: 'Launch', detail: 'Production deployment', type: 'success', completed: false } ]; return Timeline({ items: events }); }; $mount(BasicDemo, basicTarget); } // 2. Horizontal Timeline const horizontalTarget = document.querySelector('#demo-horizontal'); if (horizontalTarget && !horizontalTarget.hasChildNodes()) { const HorizontalDemo = () => { const steps = [ { title: 'Step 1', detail: 'Requirements', type: 'success', completed: true }, { title: 'Step 2', detail: 'Design', type: 'success', completed: true }, { title: 'Step 3', detail: 'Development', type: 'warning', completed: false }, { title: 'Step 4', detail: 'Testing', type: 'info', completed: false }, { title: 'Step 5', detail: 'Deploy', type: 'info', completed: false } ]; return Timeline({ items: steps, vertical: false, class: 'min-w-[600px]' }); }; $mount(HorizontalDemo, horizontalTarget); } // 3. Compact Timeline const compactTarget = document.querySelector('#demo-compact'); if (compactTarget && !compactTarget.hasChildNodes()) { const CompactDemo = () => { const activities = [ { title: 'User login', detail: '10:30 AM', type: 'success', completed: true }, { title: 'Viewed dashboard', detail: '10:32 AM', type: 'info', completed: true }, { title: 'Updated profile', detail: '10:45 AM', type: 'success', completed: true }, { title: 'Made purchase', detail: '11:00 AM', type: 'warning', completed: false } ]; return Timeline({ items: activities, compact: true }); }; $mount(CompactDemo, compactTarget); } // 4. Custom Icons const iconsTarget = document.querySelector('#demo-icons'); if (iconsTarget && !iconsTarget.hasChildNodes()) { const IconsDemo = () => { const milestones = [ { title: 'Kickoff', detail: 'Project kickoff meeting', icon: Icons.iconInfo, completed: true }, { title: 'MVP', detail: 'Minimum viable product', icon: Icons.iconSuccess, completed: true }, { title: 'Beta', detail: 'Beta release', icon: Icons.iconWarning, completed: false }, { title: 'Launch', detail: 'Public launch', icon: Icons.iconShow, completed: false } ]; return Timeline({ items: milestones }); }; $mount(IconsDemo, iconsTarget); } // 5. Reactive Timeline const reactiveTarget = document.querySelector('#demo-reactive'); if (reactiveTarget && !reactiveTarget.hasChildNodes()) { const ReactiveDemo = () => { const currentStep = $(2); const steps = [ { title: 'Order Placed', detail: 'Your order has been confirmed', type: 'success', completed: true }, { title: 'Processing', detail: 'Payment verified, preparing shipment', type: 'success', completed: currentStep() > 1 }, { title: 'Shipped', detail: 'Package on the way', type: 'warning', completed: currentStep() > 2 }, { title: 'Delivered', detail: 'Arriving soon', type: 'info', completed: currentStep() > 3 } ]; const items = () => steps.map((step, idx) => ({ ...step, completed: idx < currentStep() })); const nextStep = () => { if (currentStep() < steps.length) { currentStep(currentStep() + 1); Toast(`Step ${currentStep()}: ${steps[currentStep() - 1].title}`, 'alert-info', 1500); } }; const reset = () => { currentStep(0); Toast('Order tracking reset', 'alert-warning', 1500); }; return Div({ class: 'flex flex-col gap-4' }, [ Timeline({ items: items }), Div({ class: 'flex gap-2 justify-center mt-4' }, [ Button({ class: 'btn btn-primary btn-sm', onclick: nextStep, disabled: () => currentStep() >= steps.length }, 'Next Step'), Button({ class: 'btn btn-ghost btn-sm', onclick: reset }, 'Reset') ]) ]); }; $mount(ReactiveDemo, reactiveTarget); } // 6. Order Status Tracker const orderTarget = document.querySelector('#demo-order'); if (orderTarget && !orderTarget.hasChildNodes()) { const OrderDemo = () => { const status = $('shipped'); const statusMap = { pending: { title: 'Order Pending', detail: 'Awaiting confirmation', completed: false, type: 'warning' }, confirmed: { title: 'Order Confirmed', detail: 'Payment received', completed: false, type: 'info' }, processing: { title: 'Processing', detail: 'Preparing your order', completed: false, type: 'info' }, shipped: { title: 'Shipped', detail: 'Package in transit', completed: false, type: 'info' }, delivered: { title: 'Delivered', detail: 'Order completed', completed: false, type: 'success' } }; const statusOrder = ['pending', 'confirmed', 'processing', 'shipped', 'delivered']; const currentIndex = statusOrder.indexOf(status()); const items = statusOrder.map((key, idx) => ({ ...statusMap[key], completed: idx < currentIndex })); return Div({ class: 'flex flex-col gap-4' }, [ Timeline({ items, compact: true }), Div({ class: 'flex gap-2 justify-center flex-wrap mt-4' }, statusOrder.map(s => Button({ class: `btn btn-xs ${status() === s ? 'btn-primary' : 'btn-ghost'}`, onclick: () => status(s) }, statusMap[s].title) )) ]); }; $mount(OrderDemo, orderTarget); } // 7. Company History const historyTarget = document.querySelector('#demo-history'); if (historyTarget && !historyTarget.hasChildNodes()) { const HistoryDemo = () => { const milestones = [ { title: '2015 - Founded', detail: 'Company started with 3 employees in a small office', type: 'success', completed: true }, { title: '2017 - First Product', detail: 'Launched our first software product to market', type: 'success', completed: true }, { title: '2019 - Series A', detail: 'Raised $5M in funding, expanded team to 50', type: 'success', completed: true }, { title: '2022 - Global Expansion', detail: 'Opened offices in Europe and Asia', type: 'info', completed: true }, { title: '2024 - AI Integration', detail: 'Launched AI-powered features', type: 'warning', completed: false }, { title: '2026 - Future Goals', detail: 'Aiming for market leadership', type: 'info', completed: false } ]; return Timeline({ items: milestones }); }; $mount(HistoryDemo, historyTarget); } // 8. All Variants const variantsTarget = document.querySelector('#demo-variants'); if (variantsTarget && !variantsTarget.hasChildNodes()) { const VariantsDemo = () => { const sampleItems = [ { title: 'Event 1', detail: 'Description here', type: 'success', completed: true }, { title: 'Event 2', detail: 'Description here', type: 'warning', completed: false }, { title: 'Event 3', detail: 'Description here', type: 'info', completed: false } ]; return Div({ class: 'flex flex-col gap-8' }, [ Div({ class: 'text-sm font-bold' }, 'Vertical Timeline'), Timeline({ items: sampleItems }), Div({ class: 'text-sm font-bold mt-4' }, 'Horizontal Timeline'), Timeline({ items: sampleItems, vertical: false, class: 'min-w-[500px]' }), Div({ class: 'text-sm font-bold mt-4' }, 'Compact Timeline'), Timeline({ items: sampleItems, compact: true }) ]); }; $mount(VariantsDemo, variantsTarget); } }; initTimelineExamples(); if (window.$docsify) { window.$docsify.plugins = [].concat(window.$docsify.plugins || [], (hook) => { hook.doneEach(initTimelineExamples); }); } })(); </script>