Feedback


Toast

An imperative notification system. Call toast.* anywhere in your app — no component state required.

Setup

Place ToastContainer once at your app root:

import { ToastContainer } from '@objectifthunes/limestone-sdk';

export default function App() {
  return (
    <LimestoneProvider config={config}>
      <RootNavigator />
      <ToastContainer position="top" />
    </LimestoneProvider>
  );
}

Imperative API

import { toast } from '@objectifthunes/limestone-sdk';

// Variants
toast.success('Changes saved!');
toast.error('Something went wrong.');
toast.warning('Low disk space.');
toast.info('A new version is available.');

// Dismiss by id
const id = toast.success('Processing…');
toast.dismiss(id);

// Clear all toasts
toast.clear();

Alert

A modal alert dialog with configurable actions.

PropTypeDefaultDescription
visiblebooleanControls visibility
titlestringAlert heading
message?stringBody text
actionsAlertAction[]Array of buttons
size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Dialog width
icon?React.ReactElementIcon rendered above the title

Each AlertAction is { label: string; onPress: () => void; style?: 'default' | 'cancel' | 'destructive' }.

import { Alert } from '@objectifthunes/limestone-sdk';
import { useState } from 'react';

function DeleteButton() {
  const [visible, setVisible] = useState(false);

  return (
    <>
      <Pressable onPress={() => setVisible(true)}>
        <Text>Delete</Text>
      </Pressable>

      <Alert
        visible={visible}
        title="Delete item?"
        message="This cannot be undone."
        actions={[
          {
            label: 'Cancel',
            style: 'cancel',
            onPress: () => setVisible(false),
          },
          {
            label: 'Delete',
            style: 'destructive',
            onPress: () => {
              deleteItem();
              setVisible(false);
            },
          },
        ]}
      />
    </>
  );
}

Dialog

A structured dialog with optional close button, custom children, and a footer slot.

PropTypeDefaultDescription
visiblebooleanControls visibility
onClose() => voidClose handler
title?stringDialog heading
description?stringSubtitle text below heading
showCloseButton?booleantrueShow the X button in the top-right corner
childrenReact.ReactNodeDialog body content
footer?React.ReactNodeFooter slot (typically action buttons)
size?'sm' | 'md' | 'lg''md'Dialog width
import { Dialog, Stack, Text, Pressable, TextInput } from '@objectifthunes/limestone-sdk';
import { useState } from 'react';

function EditNameDialog({ visible, onClose }: { visible: boolean; onClose: () => void }) {
  const [name, setName] = useState('');

  return (
    <Dialog
      visible={visible}
      onClose={onClose}
      title="Edit display name"
      description="This name will be visible to other users."
      size="md"
      footer={
        <Stack direction="horizontal" gap="md" justify="flex-end">
          <Pressable onPress={onClose} bg="muted" rounded="md" px="lg" py="sm" center>
            <Text variant="label">Cancel</Text>
          </Pressable>
          <Pressable onPress={() => saveName(name)} bg="primary" rounded="md" px="lg" py="sm" center>
            <Text color="primaryForeground" variant="label">Save</Text>
          </Pressable>
        </Stack>
      }
    >
      <TextInput
        value={name}
        onChangeText={setName}
        label="Display name"
        variant="outline"
      />
    </Dialog>
  );
}

ProgressBar

A horizontal bar showing completion percentage.

PropTypeDefaultDescription
valuenumberProgress (0–100)
color?stringprimaryFilled track color
trackColor?stringmutedBackground track color
height?numberBar height in pixels
pill?booleanfalseFully rounded ends
animated?booleantrueAnimate value changes
label?stringText label rendered above the bar
showValue?booleanfalseShow percentage value
import { ProgressBar } from '@objectifthunes/limestone-sdk';

function UploadProgress({ percent }: { percent: number }) {
  return (
    <ProgressBar
      value={percent}
      label="Uploading…"
      showValue
      pill
      animated
    />
  );
}

ProgressCircle

A circular progress indicator with an optional center slot.

PropTypeDefaultDescription
valuenumberProgress (0–100)
size?number64Circle diameter in pixels
strokeWidth?number6Arc stroke width
color?stringprimaryArc color
trackColor?stringmutedBackground ring color
children?React.ReactNodeContent rendered at center
import { ProgressCircle, Text } from '@objectifthunes/limestone-sdk';

function StorageIndicator({ usedPercent }: { usedPercent: number }) {
  return (
    <ProgressCircle value={usedPercent} size={80} strokeWidth={8}>
      <Text variant="label" weight="bold">{usedPercent}%</Text>
    </ProgressCircle>
  );
}

Spinner

An activity indicator that maps token sizes to the native small / large variants.

PropTypeDefaultDescription
size?'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Spinner size (xs/sm/md → small; lg/xl → large)
color?stringprimarySpinner tint color
import { Spinner, Stack, Text } from '@objectifthunes/limestone-sdk';

function LoadingState() {
  return (
    <Stack center flex={1} gap="md">
      <Spinner size="lg" />
      <Text variant="caption" color="mutedForeground">Loading…</Text>
    </Stack>
  );
}

Badge

A small indicator overlaid on a child element. Supports count mode and dot mode.

PropTypeDefaultDescription
count?numberNumber to display; hidden when 0
maxCount?number99Values above this show as {maxCount}+
dot?booleanfalseRender a solid dot instead of a count
color?stringdestructiveBadge background color
textColor?stringdestructiveForegroundBadge text color
size?SpacingProp'sm'Badge diameter
placement?'top-right' | 'top-left''top-right'Position relative to the child
childrenReact.ReactNodeThe element the badge overlays
import { Badge, Icon } from '@objectifthunes/limestone-sdk';

// Count mode — shows number
function NotificationIcon({ unreadCount }: { unreadCount: number }) {
  return (
    <Badge count={unreadCount} maxCount={99} placement="top-right">
      <Icon name="bell" size="lg" />
    </Badge>
  );
}

// Dot mode — shows presence indicator
function OnlineAvatar() {
  return (
    <Badge dot color="green" placement="top-right">
      <Box w={40} h={40} rounded="full" bg="muted" />
    </Badge>
  );
}

A full-width inline message with four severity variants.

PropTypeDefaultDescription
messagestringPrimary message text
title?stringBold heading above the message
variant'info' | 'success' | 'warning' | 'error'Color scheme and default icon
icon?React.ReactElementOverride the default variant icon
dismissible?booleanfalseShow a dismiss button
onDismiss?() => voidCalled when the dismiss button is pressed
action?{ label: string; onPress: () => void }Optional inline action link
import { Banner } from '@objectifthunes/limestone-sdk';

// Info
<Banner
  variant="info"
  title="New version available"
  message="Update the app to get the latest features."
  action={{ label: 'Update now', onPress: openAppStore }}
/>

// Success
<Banner
  variant="success"
  message="Your profile has been updated successfully."
  dismissible
  onDismiss={() => setShowBanner(false)}
/>

// Warning
<Banner
  variant="warning"
  title="Subscription expiring"
  message="Your plan renews in 3 days."
/>

// Error
<Banner
  variant="error"
  title="Payment failed"
  message="Please update your billing information."
  action={{ label: 'Fix now', onPress: openBilling }}
/>

ConnectionStatus

A persistent bar that appears at the top of the screen when the device loses its internet connection, and auto-dismisses when connectivity is restored. It reads from the NetworkState in the Limestone store automatically.

PropTypeDefaultDescription
offlineMessage?string'No internet connection'Text shown while offline
onlineMessage?string'Back online'Text shown for a brief moment when connection is restored
showOnlineMessage?booleantrueFlash the “back online” message before hiding the bar
onlineDuration?number2000Milliseconds the “back online” bar stays visible
variant?'banner' | 'toast''banner'Render as a full-width top banner or a small toast
accessibilityLabel?stringAccessibility label
testID?stringTest identifier

Setup

Place ConnectionStatus once at your app root, alongside ToastContainer:

import { ConnectionStatus } from '@objectifthunes/limestone-sdk';

export default function App() {
  return (
    <LimestoneProvider config={config}>
      <RootNavigator />
      <ToastContainer position="top" />
      <ConnectionStatus />
    </LimestoneProvider>
  );
}

Custom messages

<ConnectionStatus
  offlineMessage="You're offline — changes will sync when reconnected."
  showOnlineMessage
  onlineMessage="Connected!"
  onlineDuration={3000}
/>