Skip to main content

LoadingOverlay

A loading mask overlay component that displays a loading indicator over content.

When to Use

  • When asynchronously loading page content
  • When performing operations that require waiting
  • Need to mask content areas and display loading state
  • When performing data requests that require waiting feedback

In Kube Design, the LoadingOverlay component provides flexible loading overlay functionality:

  • Visibility Control: Control display/hide through the visible property
  • Size Options: Support multiple loading indicator sizes
  • Customizable Overlay: Support custom overlay color and opacity
  • Position Control: Support custom z-index
  • Flexible Application: Can be used in any container component

Examples

Basic Usage

Basic loading mask usage, control display/hide through the visible property.

Live Editor
function Demo() {
  const [visible, setVisible] = React.useState(true);

  return (
    <div>
      <Button onClick={() => setVisible(!visible)} style={{ marginBottom: '16px' }}>
        Toggle Loading
      </Button>
      <LoadingOverlay visible={visible}>
        <Card style={{ padding: '40px', minHeight: '200px' }}>
          <Text>This is the content area</Text>
          <Text>Loading overlay will be displayed when visible is true</Text>
        </Card>
      </LoadingOverlay>
    </div>
  );
}
Result
Loading...

Control Visibility

Control loading state in actual application scenarios.

Live Editor
function Demo() {
  const [loading, setLoading] = React.useState(false);

  const handleLoad = () => {
    setLoading(true);
    setTimeout(() => {
      setLoading(false);
    }, 2000);
  };

  return (
    <div>
      <Button onClick={handleLoad} style={{ marginBottom: '16px' }}>
        Simulate Loading (2 seconds)
      </Button>
      <LoadingOverlay visible={loading}>
        <Card style={{ padding: '40px', minHeight: '200px' }}>
          <Text weight={600} style={{ marginBottom: '8px' }}>
            Data Display Area
          </Text>
          <Text size="sm">Click the button above to simulate data loading</Text>
        </Card>
      </LoadingOverlay>
    </div>
  );
}
Result
Loading...

Different Sizes

Set loading indicator size through the size property.

Live Editor
function Demo() {
  return (
    <Group direction="column" spacing="md">
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          Small Size (xs):
        </Text>
        <LoadingOverlay visible size="xs">
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>Content Area</Text>
          </Card>
        </LoadingOverlay>
      </div>
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          Medium Size (md - Default):
        </Text>
        <LoadingOverlay visible size="md">
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>Content Area</Text>
          </Card>
        </LoadingOverlay>
      </div>
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          Large Size (xl):
        </Text>
        <LoadingOverlay visible size="xl">
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>Content Area</Text>
          </Card>
        </LoadingOverlay>
      </div>
    </Group>
  );
}
Result
Loading...

Custom Overlay Color

Customize overlay background color through the overlayColor property.

Live Editor
function Demo() {
  return (
    <Group direction="column" spacing="md">
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          Default Color (white):
        </Text>
        <LoadingOverlay visible>
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>Content Area</Text>
          </Card>
        </LoadingOverlay>
      </div>
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          Dark Background:
        </Text>
        <LoadingOverlay visible overlayColor="#242e42">
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>Content Area</Text>
          </Card>
        </LoadingOverlay>
      </div>
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          Light Blue Background:
        </Text>
        <LoadingOverlay visible overlayColor="#e3f2fd">
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>Content Area</Text>
          </Card>
        </LoadingOverlay>
      </div>
    </Group>
  );
}
Result
Loading...

Custom Opacity

Control overlay transparency through the overlayOpacity property.

Live Editor
function Demo() {
  return (
    <Group direction="column" spacing="md">
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          Low Opacity (0.3):
        </Text>
        <LoadingOverlay visible overlayOpacity={0.3}>
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>You can partially see the background content</Text>
          </Card>
        </LoadingOverlay>
      </div>
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          Medium Opacity (0.6 - Default):
        </Text>
        <LoadingOverlay visible overlayOpacity={0.6}>
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>Default opacity effect</Text>
          </Card>
        </LoadingOverlay>
      </div>
      <div>
        <Text size="sm" style={{ marginBottom: '8px' }}>
          High Opacity (0.9):
        </Text>
        <LoadingOverlay visible overlayOpacity={0.9}>
          <Card style={{ padding: '40px', minHeight: '150px' }}>
            <Text>Background content almost completely hidden</Text>
          </Card>
        </LoadingOverlay>
      </div>
    </Group>
  );
}
Result
Loading...

Use in Cards

Commonly used with Card components to mask content areas.

Live Editor
function Demo() {
  const [loading1, setLoading1] = React.useState(false);
  const [loading2, setLoading2] = React.useState(false);

  const handleLoad1 = () => {
    setLoading1(true);
    setTimeout(() => setLoading1(false), 1500);
  };

  const handleLoad2 = () => {
    setLoading2(true);
    setTimeout(() => setLoading2(false), 1500);
  };

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px' }}>
      <div>
        <LoadingOverlay visible={loading1}>
          <Card>
            <Text weight={600} style={{ marginBottom: '12px' }}>
              User Statistics
            </Text>
            <Text size="sm">Total Users: 1,234</Text>
            <Text size="sm">Active Users: 567</Text>
            <Text size="sm">New Users Today: 89</Text>
            <Button size="sm" style={{ marginTop: '12px' }} onClick={handleLoad1}>
              Refresh Data
            </Button>
          </Card>
        </LoadingOverlay>
      </div>
      <div>
        <LoadingOverlay visible={loading2}>
          <Card>
            <Text weight={600} style={{ marginBottom: '12px' }}>
              System Status
            </Text>
            <Text size="sm">CPU Usage: 45%</Text>
            <Text size="sm">Memory Usage: 62%</Text>
            <Text size="sm">Disk Usage: 38%</Text>
            <Button size="sm" style={{ marginTop: '12px' }} onClick={handleLoad2}>
              Refresh Data
            </Button>
          </Card>
        </LoadingOverlay>
      </div>
    </div>
  );
}
Result
Loading...

Full Page Loading

Use with full screen elements to create full page loading effect.

Live Editor
function Demo() {
  const [loading, setLoading] = React.useState(false);

  const handleLoad = () => {
    setLoading(true);
    setTimeout(() => setLoading(false), 2000);
  };

  return (
    <div>
      <Button onClick={handleLoad} style={{ marginBottom: '16px' }}>
        Simulate Page Loading
      </Button>
      <LoadingOverlay visible={loading} zIndex={1000}>
        <div style={{ minHeight: '300px', padding: '20px', background: '#f7f8fa', borderRadius: '4px' }}>
          <Text weight={600} style={{ marginBottom: '16px' }}>
            Page Content
          </Text>
          <Text>This is a simulated page content area</Text>
          <Text>Loading overlay will cover the entire area when loading</Text>
        </div>
      </LoadingOverlay>
    </div>
  );
}
Result
Loading...

With Custom Loading Indicator

Combine with different loading indicator variants.

Live Editor
function Demo() {
  const [variant, setVariant] = React.useState('circle1');

  return (
    <div>
      <Group spacing="xs" style={{ marginBottom: '16px' }}>
        <Button size="sm" variant={variant === 'circle1' ? 'filled' : 'outline'} onClick={() => setVariant('circle1')}>
          Circle 1
        </Button>
        <Button size="sm" variant={variant === 'circle2' ? 'filled' : 'outline'} onClick={() => setVariant('circle2')}>
          Circle 2
        </Button>
      </Group>
      <LoadingOverlay visible variant={variant}>
        <Card style={{ padding: '40px', minHeight: '200px' }}>
          <Text>Content area displays different loading animation styles</Text>
        </Card>
      </LoadingOverlay>
    </div>
  );
}
Result
Loading...

API

LoadingOverlay Properties

PropertyDescriptionTypeDefault
visibleWhether to display loading overlaybooleanfalse
sizeLoading indicator size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'
variantLoading indicator variant'circle1' | 'circle2''circle1'
overlayColorOverlay background colorstring'#fff'
overlayOpacityOverlay opacity (0-1)number0.6
zIndexz-index valuenumber1
childrenContent to be maskedReactNode-
info

About visible property:

  • Controls whether to display the loading overlay
  • When visible={false}, only the children content is displayed
  • When visible={true}, displays loading indicator and mask layer over content
  • Commonly used with state management for dynamic control

About size:

  • Supports size options: xs, sm, md, lg, xl
  • Default is md
  • Only affects loading indicator size, not overlay area size
  • Overlay area size is determined by children container size

About variant:

  • circle1: Default circular loading animation
  • circle2: Alternative circular loading animation style
  • Both styles support all size options

About overlayColor:

  • Sets the background color of the mask layer
  • Default is white #fff
  • Supports any valid CSS color value (hex, rgb, rgba, color names, etc.)
  • Light backgrounds commonly use white/light colors, dark backgrounds use dark colors

About overlayOpacity:

  • Controls mask layer transparency
  • Value range: 0-1
  • Default is 0.6 (60% opacity)
  • 0 is completely transparent (not recommended, mask effect disappears)
  • 1 is completely opaque (background content completely hidden)

About zIndex:

  • Controls the stacking order of the loading overlay
  • Default is 1
  • Increase this value when needing to override other elements
  • For full page loading, set higher value (like 1000)

About position relationship:

  • LoadingOverlay uses position: relative for wrapper (LoadingOverlay.tsx line 25)
  • Overlay uses position: absolute covering entire container (line 37)
  • Children content maintains normal document flow

About animation:

  • Loading indicator uses Loading component (LoadingOverlay.tsx lines 50-52)
  • Supports all Loading component properties (size, variant, color)
  • Overlay layer has fade-in/fade-out transition animation

Usage Recommendations

Appropriate Use Scenarios

Use loading overlay in appropriate scenarios:

// Recommended: Use when loading data
const [loading, setLoading] = React.useState(false);

const fetchData = async () => {
setLoading(true);
try {
const data = await api.getData();
// Process data...
} finally {
setLoading(false);
}
};

<LoadingOverlay visible={loading}>
<DataDisplay />
</LoadingOverlay>;

// Not recommended: Don't use for very short operations (< 300ms)
// Users may see brief flashing

Set Appropriate Opacity

Choose appropriate opacity based on scenario:

// For important operations: higher opacity to prevent user interaction
<LoadingOverlay visible={loading} overlayOpacity={0.8}>
<ImportantForm />
</LoadingOverlay>

// For background loading: lower opacity to allow viewing content
<LoadingOverlay visible={loading} overlayOpacity={0.4}>
<DataList />
</LoadingOverlay>

Choose Appropriate Size

Select loading indicator size based on container size:

// Small containers use small indicators
<LoadingOverlay visible={loading} size="xs">
<SmallCard />
</LoadingOverlay>

// Large areas use large indicators
<LoadingOverlay visible={loading} size="xl">
<FullPageContent />
</LoadingOverlay>

Prevent Unnecessary Re-renders

Use proper state management to avoid unnecessary re-renders:

// Recommended: Loading state only affects necessary areas
const [dataLoading, setDataLoading] = React.useState(false);

<LoadingOverlay visible={dataLoading}>
<DataArea />
</LoadingOverlay>

// Not recommended: Entire page loading affects all components
const [pageLoading, setPageLoading] = React.useState(false);

Combine with Error Handling

Provide proper error feedback:

const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState(null);

const loadData = async () => {
setLoading(true);
setError(null);
try {
await fetchData();
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

<>
<LoadingOverlay visible={loading}>
<DataDisplay />
</LoadingOverlay>
{error && <Alert type="error">{error}</Alert>}
</>;

Use with Skeleton Screens

For first load, consider using skeleton screens:

const [firstLoad, setFirstLoad] = React.useState(true);
const [loading, setLoading] = React.useState(false);

// First load shows skeleton screen
if (firstLoad) {
return <SkeletonScreen />;
}

// Subsequent loads use loading overlay
return (
<LoadingOverlay visible={loading}>
<DataDisplay />
</LoadingOverlay>
);

Set Appropriate z-index

Set appropriate z-index based on context:

// Regular content area
<LoadingOverlay visible={loading} zIndex={1}>
<Content />
</LoadingOverlay>

// Modal loading
<Modal>
<LoadingOverlay visible={loading} zIndex={1001}>
<ModalContent />
</LoadingOverlay>
</Modal>

// Full page loading
<LoadingOverlay visible={loading} zIndex={9999}>
<PageContent />
</LoadingOverlay>

Coordinate Overlay Color with Theme

Choose appropriate overlay color based on theme:

// Light theme uses white background
<LoadingOverlay visible={loading} overlayColor="#fff" overlayOpacity={0.6}>
<LightThemeContent />
</LoadingOverlay>

// Dark theme uses dark background
<LoadingOverlay visible={loading} overlayColor="#242e42" overlayOpacity={0.7}>
<DarkThemeContent />
</LoadingOverlay>

Provide User Feedback

Consider providing additional feedback for long operations:

const [loading, setLoading] = React.useState(false);
const [progress, setProgress] = React.useState(0);

<>
<LoadingOverlay visible={loading}>
<DataArea />
</LoadingOverlay>
{loading && <Text size="sm">Loading... {progress}%</Text>}
</>;