Files
sigpro-ui/docs/components_old/loading.md
2026-04-06 03:19:15 +02:00

21 KiB

Loading

Loading spinner component for indicating loading states with customizable size and colors.

Tag

Loading

Props

Prop Type Default Description
$show boolean | Signal<boolean> true Show/hide the loading spinner
class string '' Additional CSS classes (DaisyUI loading variants)

Live Examples

Basic Loading

Live Demo

const BasicDemo = () => {
  return Div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [
    Loading({ $show: true, class: 'loading-spinner' }),
    Loading({ $show: true, class: 'loading-dots' }),
    Loading({ $show: true, class: 'loading-ring' }),
    Loading({ $show: true, class: 'loading-ball' }),
    Loading({ $show: true, class: 'loading-bars' }),
    Loading({ $show: true, class: 'loading-infinity' })
  ]);
};
Mount(BasicDemo, '#demo-basic');

Loading Sizes

Live Demo

const SizesDemo = () => {
  return Div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [
    Div({ class: 'text-center' }, [
      Loading({ $show: true, class: 'loading-spinner loading-xs' }),
      Div({ class: 'text-xs mt-2' }, 'Extra Small')
    ]),
    Div({ class: 'text-center' }, [
      Loading({ $show: true, class: 'loading-spinner loading-sm' }),
      Div({ class: 'text-xs mt-2' }, 'Small')
    ]),
    Div({ class: 'text-center' }, [
      Loading({ $show: true, class: 'loading-spinner loading-md' }),
      Div({ class: 'text-xs mt-2' }, 'Medium')
    ]),
    Div({ class: 'text-center' }, [
      Loading({ $show: true, class: 'loading-spinner loading-lg' }),
      Div({ class: 'text-xs mt-2' }, 'Large')
    ])
  ]);
};
Mount(SizesDemo, '#demo-sizes');

Loading Colors

Live Demo

const ColorsDemo = () => {
  return Div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [
    Loading({ $show: true, class: 'loading-spinner text-primary' }),
    Loading({ $show: true, class: 'loading-spinner text-secondary' }),
    Loading({ $show: true, class: 'loading-spinner text-accent' }),
    Loading({ $show: true, class: 'loading-spinner text-info' }),
    Loading({ $show: true, class: 'loading-spinner text-success' }),
    Loading({ $show: true, class: 'loading-spinner text-warning' }),
    Loading({ $show: true, class: 'loading-spinner text-error' })
  ]);
};
Mount(ColorsDemo, '#demo-colors');

Button Loading State

Live Demo

const ButtonDemo = () => {
  const isLoading = $(false);
  
  const handleClick = async () => {
    isLoading(true);
    await new Promise(resolve => setTimeout(resolve, 2000));
    isLoading(false);
    Toast('Operation completed!', 'alert-success', 2000);
  };
  
  return Div({ class: 'flex flex-col gap-4 items-center' }, [
    Button({ 
      class: 'btn btn-primary',
      loading: isLoading,
      onclick: handleClick
    }, 'Submit'),
    Div({ class: 'text-sm opacity-70' }, 'Click the button to see loading state')
  ]);
};
Mount(ButtonDemo, '#demo-button');

Async Data Loading

Live Demo

const AsyncDemo = () => {
  const loading = $(false);
  const data = $(null);
  const error = $(null);
  
  const loadData = async () => {
    loading(true);
    error(null);
    data(null);
    
    try {
      await new Promise(resolve => setTimeout(resolve, 2000));
      const result = {
        users: 1234,
        posts: 5678,
        comments: 9012
      };
      data(result);
      Toast('Data loaded successfully!', 'alert-success', 2000);
    } catch (err) {
      error('Failed to load data');
      Toast('Error loading data', 'alert-error', 2000);
    } finally {
      loading(false);
    }
  };
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'flex justify-center' }, [
      Button({ 
        class: 'btn btn-primary',
        onclick: loadData,
        disabled: () => loading()
      }, loading() ? 'Loading...' : 'Load Data')
    ]),
    Div({ class: 'relative min-h-[200px] flex items-center justify-center' }, [
      () => loading() ? Loading({ $show: true, class: 'loading-spinner loading-lg' }) : null,
      () => data() ? Div({ class: 'grid grid-cols-3 gap-4 w-full' }, [
        Div({ class: 'stat' }, [
          Div({ class: 'stat-title' }, 'Users'),
          Div({ class: 'stat-value' }, data().users)
        ]),
        Div({ class: 'stat' }, [
          Div({ class: 'stat-title' }, 'Posts'),
          Div({ class: 'stat-value' }, data().posts)
        ]),
        Div({ class: 'stat' }, [
          Div({ class: 'stat-title' }, 'Comments'),
          Div({ class: 'stat-value' }, data().comments)
        ])
      ]) : null,
      () => error() ? Alert({ type: 'error', message: error() }) : null
    ])
  ]);
};
Mount(AsyncDemo, '#demo-async');

Full Page Loading

Live Demo

const FullpageDemo = () => {
  const isLoading = $(false);
  
  const simulatePageLoad = () => {
    isLoading(true);
    setTimeout(() => {
      isLoading(false);
      Toast('Page loaded!', 'alert-success', 2000);
    }, 2000);
  };
  
  return Div({ class: 'relative' }, [
    Div({ class: 'flex justify-center p-8' }, [
      Button({ 
        class: 'btn btn-primary',
        onclick: simulatePageLoad
      }, 'Simulate Page Load')
    ]),
    () => isLoading() ? Loading({ $show: true, class: 'loading-spinner loading-lg' }) : null
  ]);
};
Mount(FullpageDemo, '#demo-fullpage');

Conditional Loading

Live Demo

const ConditionalDemo = () => {
  const loadingState = $('idle');
  const content = $('');
  
  const simulateAction = (action) => {
    loadingState('loading');
    setTimeout(() => {
      content(`Action: ${action} completed at ${new Date().toLocaleTimeString()}`);
      loadingState('success');
      setTimeout(() => loadingState('idle'), 1500);
    }, 1500);
  };
  
  const loadingStates = {
    idle: null,
    loading: Loading({ $show: true, class: 'loading-spinner text-primary' }),
    success: Alert({ type: 'success', message: '✓ Done!' })
  };
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'flex gap-2 justify-center' }, [
      Button({ 
        class: 'btn btn-sm',
        onclick: () => simulateAction('Save')
      }, 'Save'),
      Button({ 
        class: 'btn btn-sm',
        onclick: () => simulateAction('Update')
      }, 'Update'),
      Button({ 
        class: 'btn btn-sm',
        onclick: () => simulateAction('Delete')
      }, 'Delete')
    ]),
    Div({ class: 'flex justify-center min-h-[100px] items-center' }, [
      () => loadingStates[loadingState()],
      () => content() && loadingState() === 'idle' ? Div({ class: 'text-center' }, content()) : null
    ])
  ]);
};
Mount(ConditionalDemo, '#demo-conditional');

All Variants

Live Demo

const VariantsDemo = () => {
  return Div({ class: 'flex flex-col gap-6' }, [
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'Spinner'),
      Div({ class: 'flex gap-4 justify-center' }, [
        Loading({ $show: true, class: 'loading-spinner loading-xs' }),
        Loading({ $show: true, class: 'loading-spinner loading-sm' }),
        Loading({ $show: true, class: 'loading-spinner loading-md' }),
        Loading({ $show: true, class: 'loading-spinner loading-lg' })
      ])
    ]),
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'Dots'),
      Div({ class: 'flex gap-4 justify-center' }, [
        Loading({ $show: true, class: 'loading-dots loading-xs' }),
        Loading({ $show: true, class: 'loading-dots loading-sm' }),
        Loading({ $show: true, class: 'loading-dots loading-md' }),
        Loading({ $show: true, class: 'loading-dots loading-lg' })
      ])
    ]),
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'Ring'),
      Div({ class: 'flex gap-4 justify-center' }, [
        Loading({ $show: true, class: 'loading-ring loading-xs' }),
        Loading({ $show: true, class: 'loading-ring loading-sm' }),
        Loading({ $show: true, class: 'loading-ring loading-md' }),
        Loading({ $show: true, class: 'loading-ring loading-lg' })
      ])
    ])
  ]);
};
Mount(VariantsDemo, '#demo-variants');
<script> (function() { const initLoadingExamples = () => { // 1. Basic Loading const basicTarget = document.querySelector('#demo-basic'); if (basicTarget && !basicTarget.hasChildNodes()) { const BasicDemo = () => { return Div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [ Loading({ $show: true, class: 'loading-spinner' }), Loading({ $show: true, class: 'loading-dots' }), Loading({ $show: true, class: 'loading-ring' }), Loading({ $show: true, class: 'loading-ball' }), Loading({ $show: true, class: 'loading-bars' }), Loading({ $show: true, class: 'loading-infinity' }) ]); }; Mount(BasicDemo, basicTarget); } // 2. Loading Sizes const sizesTarget = document.querySelector('#demo-sizes'); if (sizesTarget && !sizesTarget.hasChildNodes()) { const SizesDemo = () => { return Div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [ Div({ class: 'text-center' }, [ Loading({ $show: true, class: 'loading-spinner loading-xs' }), Div({ class: 'text-xs mt-2' }, 'Extra Small') ]), Div({ class: 'text-center' }, [ Loading({ $show: true, class: 'loading-spinner loading-sm' }), Div({ class: 'text-xs mt-2' }, 'Small') ]), Div({ class: 'text-center' }, [ Loading({ $show: true, class: 'loading-spinner loading-md' }), Div({ class: 'text-xs mt-2' }, 'Medium') ]), Div({ class: 'text-center' }, [ Loading({ $show: true, class: 'loading-spinner loading-lg' }), Div({ class: 'text-xs mt-2' }, 'Large') ]) ]); }; Mount(SizesDemo, sizesTarget); } // 3. Loading Colors const colorsTarget = document.querySelector('#demo-colors'); if (colorsTarget && !colorsTarget.hasChildNodes()) { const ColorsDemo = () => { return Div({ class: 'flex flex-wrap gap-8 justify-center items-center' }, [ Loading({ $show: true, class: 'loading-spinner text-primary' }), Loading({ $show: true, class: 'loading-spinner text-secondary' }), Loading({ $show: true, class: 'loading-spinner text-accent' }), Loading({ $show: true, class: 'loading-spinner text-info' }), Loading({ $show: true, class: 'loading-spinner text-success' }), Loading({ $show: true, class: 'loading-spinner text-warning' }), Loading({ $show: true, class: 'loading-spinner text-error' }) ]); }; Mount(ColorsDemo, colorsTarget); } // 4. Button Loading State const buttonTarget = document.querySelector('#demo-button'); if (buttonTarget && !buttonTarget.hasChildNodes()) { const ButtonDemo = () => { const isLoading = $(false); const handleClick = async () => { isLoading(true); await new Promise(resolve => setTimeout(resolve, 2000)); isLoading(false); Toast('Operation completed!', 'alert-success', 2000); }; return Div({ class: 'flex flex-col gap-4 items-center' }, [ Button({ class: 'btn btn-primary', loading: isLoading, onclick: handleClick }, 'Submit'), Div({ class: 'text-sm opacity-70' }, 'Click the button to see loading state') ]); }; Mount(ButtonDemo, buttonTarget); } // 5. Async Data Loading const asyncTarget = document.querySelector('#demo-async'); if (asyncTarget && !asyncTarget.hasChildNodes()) { const AsyncDemo = () => { const loading = $(false); const data = $(null); const error = $(null); const loadData = async () => { loading(true); error(null); data(null); try { await new Promise(resolve => setTimeout(resolve, 2000)); const result = { users: 1234, posts: 5678, comments: 9012 }; data(result); Toast('Data loaded successfully!', 'alert-success', 2000); } catch (err) { error('Failed to load data'); Toast('Error loading data', 'alert-error', 2000); } finally { loading(false); } }; return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'flex justify-center' }, [ Button({ class: 'btn btn-primary', onclick: loadData, disabled: () => loading() }, loading() ? 'Loading...' : 'Load Data') ]), Div({ class: 'relative min-h-[200px] flex items-center justify-center' }, [ () => loading() ? Loading({ $show: true, class: 'loading-spinner loading-lg' }) : null, () => data() ? Div({ class: 'grid grid-cols-3 gap-4 w-full' }, [ Div({ class: 'stat' }, [ Div({ class: 'stat-title' }, 'Users'), Div({ class: 'stat-value' }, data().users) ]), Div({ class: 'stat' }, [ Div({ class: 'stat-title' }, 'Posts'), Div({ class: 'stat-value' }, data().posts) ]), Div({ class: 'stat' }, [ Div({ class: 'stat-title' }, 'Comments'), Div({ class: 'stat-value' }, data().comments) ]) ]) : null, () => error() ? Alert({ type: 'error', message: error() }) : null ]) ]); }; Mount(AsyncDemo, asyncTarget); } // 6. Full Page Loading const fullpageTarget = document.querySelector('#demo-fullpage'); if (fullpageTarget && !fullpageTarget.hasChildNodes()) { const FullpageDemo = () => { const isLoading = $(false); const simulatePageLoad = () => { isLoading(true); setTimeout(() => { isLoading(false); Toast('Page loaded!', 'alert-success', 2000); }, 2000); }; return Div({ class: 'relative' }, [ Div({ class: 'flex justify-center p-8' }, [ Button({ class: 'btn btn-primary', onclick: simulatePageLoad }, 'Simulate Page Load') ]), () => isLoading() ? Loading({ $show: true, class: 'loading-spinner loading-lg' }) : null ]); }; Mount(FullpageDemo, fullpageTarget); } // 7. Conditional Loading const conditionalTarget = document.querySelector('#demo-conditional'); if (conditionalTarget && !conditionalTarget.hasChildNodes()) { const ConditionalDemo = () => { const loadingState = $('idle'); const content = $(''); const simulateAction = (action) => { loadingState('loading'); setTimeout(() => { content(`Action: ${action} completed at ${new Date().toLocaleTimeString()}`); loadingState('success'); setTimeout(() => loadingState('idle'), 1500); }, 1500); }; const loadingStates = { idle: null, loading: Loading({ $show: true, class: 'loading-spinner text-primary' }), success: Alert({ type: 'success', message: '✓ Done!' }) }; return Div({ class: 'flex flex-col gap-4' }, [ Div({ class: 'flex gap-2 justify-center' }, [ Button({ class: 'btn btn-sm', onclick: () => simulateAction('Save') }, 'Save'), Button({ class: 'btn btn-sm', onclick: () => simulateAction('Update') }, 'Update'), Button({ class: 'btn btn-sm', onclick: () => simulateAction('Delete') }, 'Delete') ]), Div({ class: 'flex justify-center min-h-[100px] items-center' }, [ () => loadingStates[loadingState()], () => content() && loadingState() === 'idle' ? Div({ class: 'text-center' }, content()) : null ]) ]); }; Mount(ConditionalDemo, conditionalTarget); } // 8. All Variants const variantsTarget = document.querySelector('#demo-variants'); if (variantsTarget && !variantsTarget.hasChildNodes()) { const VariantsDemo = () => { return Div({ class: 'flex flex-col gap-6' }, [ Div({ class: 'text-center' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'Spinner'), Div({ class: 'flex gap-4 justify-center' }, [ Loading({ $show: true, class: 'loading-spinner loading-xs' }), Loading({ $show: true, class: 'loading-spinner loading-sm' }), Loading({ $show: true, class: 'loading-spinner loading-md' }), Loading({ $show: true, class: 'loading-spinner loading-lg' }) ]) ]), Div({ class: 'text-center' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'Dots'), Div({ class: 'flex gap-4 justify-center' }, [ Loading({ $show: true, class: 'loading-dots loading-xs' }), Loading({ $show: true, class: 'loading-dots loading-sm' }), Loading({ $show: true, class: 'loading-dots loading-md' }), Loading({ $show: true, class: 'loading-dots loading-lg' }) ]) ]), Div({ class: 'text-center' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'Ring'), Div({ class: 'flex gap-4 justify-center' }, [ Loading({ $show: true, class: 'loading-ring loading-xs' }), Loading({ $show: true, class: 'loading-ring loading-sm' }), Loading({ $show: true, class: 'loading-ring loading-md' }), Loading({ $show: true, class: 'loading-ring loading-lg' }) ]) ]) ]); }; Mount(VariantsDemo, variantsTarget); } }; initLoadingExamples(); if (window.$docsify) { window.$docsify.plugins = [].concat(window.$docsify.plugins || [], (hook) => { hook.doneEach(initLoadingExamples); }); } })(); </script>