Files
sigpro-ui/docs/components/stack.md
2026-04-03 01:41:07 +02:00

10 KiB
Raw Blame History

Stack

Stack component for layering multiple elements on top of each other, creating depth and visual hierarchy.

Tag

Stack

Props

Prop Type Default Description
class string '' Additional CSS classes (DaisyUI + Tailwind)
children Array<VNode> | VNode - Elements to stack (first is bottom, last is top)

Styling

Stack supports all daisyUI Stack classes:

Category Keywords Description
Base stack Base stack container
Direction stack-top, stack-bottom, stack-start, stack-end Stack alignment
Width w-* (Tailwind) Custom width for the stack

For further details, check the daisyUI Stack Documentation Full reference for CSS classes.

Live Examples

Basic Stack

Live Demo

const BasicDemo = () => {
  return Stack({ class: 'w-40' }, [
    Div({ class: 'bg-primary text-primary-content rounded-lg p-4 shadow-lg' }, 'Layer 1'),
    Div({ class: 'bg-secondary text-secondary-content rounded-lg p-4 shadow-lg' }, 'Layer 2'),
    Div({ class: 'bg-accent text-accent-content rounded-lg p-4 shadow-lg' }, 'Layer 3')
  ]);
};
$mount(BasicDemo, '#demo-basic');

Card Stack

Live Demo

const CardsDemo = () => {
  return Stack({ class: 'w-64' }, [
    Div({ class: 'card bg-base-100 shadow-xl border border-base-300' }, [
      Div({ class: 'card-body p-4' }, [
        Span({ class: 'text-sm opacity-70' }, 'Back Card'),
        Span({ class: 'font-bold' }, 'Additional info')
      ])
    ]),
    Div({ class: 'card bg-primary text-primary-content shadow-xl' }, [
      Div({ class: 'card-body p-4' }, [
        Span({ class: 'text-sm' }, 'Front Card'),
        Span({ class: 'font-bold text-lg' }, 'Main Content')
      ])
    ])
  ]);
};
$mount(CardsDemo, '#demo-cards');

Avatar Stack

Live Demo

const AvatarsDemo = () => {
  return Stack({ class: 'w-32' }, [
    Div({ class: 'avatar placeholder' }, [
      Div({ class: 'bg-neutral text-neutral-content rounded-full w-16 h-16 flex items-center justify-center' }, 'JD')
    ]),
    Div({ class: 'avatar placeholder' }, [
      Div({ class: 'bg-primary text-primary-content rounded-full w-16 h-16 flex items-center justify-center' }, 'JS')
    ]),
    Div({ class: 'avatar placeholder' }, [
      Div({ class: 'bg-secondary text-secondary-content rounded-full w-16 h-16 flex items-center justify-center' }, 'BC')
    ])
  ]);
};
$mount(AvatarsDemo, '#demo-avatars');

Image Stack

Live Demo

const ImagesDemo = () => {
  return Stack({ class: 'w-48' }, [
    Div({ class: 'w-full h-32 bg-gradient-to-r from-primary to-secondary rounded-lg shadow-lg' }, [
      Div({ class: 'p-2 text-white text-sm' }, 'Background Image')
    ]),
    Div({ class: 'w-full h-32 bg-gradient-to-r from-secondary to-accent rounded-lg shadow-lg translate-x-2 translate-y-2' }, [
      Div({ class: 'p-2 text-white text-sm' }, 'Middle Layer')
    ]),
    Div({ class: 'w-full h-32 bg-gradient-to-r from-accent to-primary rounded-lg shadow-lg translate-x-4 translate-y-4 flex items-center justify-center' }, [
      Span({ class: 'text-white font-bold' }, 'Top Layer')
    ])
  ]);
};
$mount(ImagesDemo, '#demo-images');

Live Demo

const GalleryDemo = () => {
  const photos = [
    { color: 'bg-primary', label: 'Photo 1' },
    { color: 'bg-secondary', label: 'Photo 2' },
    { color: 'bg-accent', label: 'Photo 3' },
    { color: 'bg-info', label: 'Photo 4' }
  ];
  
  return Stack({ class: 'w-48 cursor-pointer hover:scale-105 transition-transform' }, [
    ...photos.map((photo, idx) => 
      Div({ 
        class: `${photo.color} rounded-lg shadow-lg transition-all`,
        style: `transform: translate(${idx * 4}px, ${idx * 4}px);`
      }, [
        Div({ class: 'p-4 text-white font-bold' }, photo.label)
      ])
    )
  ]);
};
$mount(GalleryDemo, '#demo-gallery');

Interactive Stack

Live Demo

const InteractiveDemo = () => {
  const active = $(0);
  const colors = ['primary', 'secondary', 'accent', 'info', 'success'];
  const labels = ['Home', 'Profile', 'Settings', 'Messages', 'Notifications'];
  
  return Div({ class: 'flex flex-col gap-6 items-center' }, [
    Stack({ class: 'w-56' }, colors.map((color, idx) => 
      Div({ 
        class: () => `bg-${color} text-${color}-content rounded-lg p-4 shadow-lg transition-all cursor-pointer ${idx === active() ? 'scale-105 z-10' : ''}`,
        style: () => `transform: translate(${idx * 8}px, ${idx * 8}px);`,
        onclick: () => active(idx)
      }, [
        Div({ class: 'font-bold' }, labels[idx]),
        Div({ class: 'text-sm opacity-80' }, `Layer ${idx + 1}`)
      ])
    )),
    Div({ class: 'mt-4 text-center' }, [
      Span({ class: 'font-bold' }, () => `Active: ${labels[active()]}`),
      Div({ class: 'flex gap-2 mt-2' }, colors.map((_, idx) =>
        Button({ 
          class: () => `btn btn-xs ${idx === active() ? 'btn-primary' : 'btn-ghost'}`,
          onclick: () => active(idx)
        }, `${idx + 1}`)
      ))
    ])
  ]);
};
$mount(InteractiveDemo, '#demo-interactive');

Notification Stack

Live Demo

const NotificationsDemo = () => {
  const notifications = $([
    { id: 1, message: 'New message from John', type: 'info' },
    { id: 2, message: 'Your order has shipped', type: 'success' },
    { id: 3, message: 'Meeting in 10 minutes', type: 'warning' }
  ]);
  
  const removeNotification = (id) => {
    notifications(notifications().filter(n => n.id !== id));
  };
  
  const typeClasses = {
    info: 'bg-info text-info-content',
    success: 'bg-success text-success-content',
    warning: 'bg-warning text-warning-content',
    error: 'bg-error text-error-content'
  };
  
  return Div({ class: 'flex flex-col gap-4 items-center' }, [
    Stack({ class: 'w-80' }, () => notifications().map((notif, idx) => 
      Div({ 
        class: () => `${typeClasses[notif.type]} rounded-lg p-3 shadow-lg transition-all cursor-pointer`,
        style: () => `transform: translate(${idx * 4}px, ${idx * 4}px);`,
        onclick: () => removeNotification(notif.id)
      }, [
        Div({ class: 'flex justify-between items-center' }, [
          Span({ class: 'text-sm' }, notif.message),
          Span({ class: 'text-xs opacity-70 cursor-pointer hover:opacity-100' }, '✕')
        ])
      ])
    )),
    () => notifications().length === 0 
      ? Div({ class: 'alert alert-soft' }, 'No notifications')
      : Button({ 
          class: 'btn btn-sm btn-ghost mt-2',
          onclick: () => notifications([])
        }, 'Clear All')
  ]);
};
$mount(NotificationsDemo, '#demo-notifications');

All Variants

Live Demo

const VariantsDemo = () => {
  return Div({ class: 'flex flex-wrap gap-8 justify-center' }, [
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm mb-2' }, 'Small Stack'),
      Stack({ class: 'w-24' }, [
        Div({ class: 'bg-primary rounded p-2 text-xs' }, '1'),
        Div({ class: 'bg-secondary rounded p-2 text-xs' }, '2'),
        Div({ class: 'bg-accent rounded p-2 text-xs' }, '3')
      ])
    ]),
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm mb-2' }, 'Medium Stack'),
      Stack({ class: 'w-32' }, [
        Div({ class: 'bg-primary rounded p-3' }, 'A'),
        Div({ class: 'bg-secondary rounded p-3' }, 'B'),
        Div({ class: 'bg-accent rounded p-3' }, 'C')
      ])
    ]),
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm mb-2' }, 'Large Stack'),
      Stack({ class: 'w-40' }, [
        Div({ class: 'bg-primary rounded p-4' }, 'X'),
        Div({ class: 'bg-secondary rounded p-4' }, 'Y'),
        Div({ class: 'bg-accent rounded p-4' }, 'Z')
      ])
    ])
  ]);
};
$mount(VariantsDemo, '#demo-variants');