Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions apps/docs/pages/docs/v2/Components/spinner.en-US.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
searchable: true
---

import { CodeEditor } from '@components/code-editor';

# Spinner

Simple spinner component that is based on react native `ActivityIndicator` component.

## Import

```js
import { Spinner } from "@ficus-ui/native";
import PropsTable from "@components/docs/props-table";
```

## Usage

<CodeEditor code={`<HStack spacing={10}>
<Spinner />
<Spinner color="blue.500" size="sm" />
<Spinner color="red.500" size="lg" />
<Spinner color="green.500" size="lg" />
<Spinner color="pink.500" size="lg" />
</HStack>`} />

## Props

Extends every `Box` props and react native `ActivityIndicator` component.

https://reactnative.dev/docs/activityindicator#props

### `color`
<PropsTable
description="The color property for `ActivityIndicator`."
prop={{ type: "string", required: false }}
/>

### `size`
<PropsTable
description="The size property for `ActivityIndicator`."
prop={{ type: "number, string", required: false }}
/>
29 changes: 29 additions & 0 deletions apps/examples/app/components-v2/Spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import ExampleSection from "@/src/ExampleSection";
import { Box, SafeAreaBox, Spinner, Spinner2, Text } from "@ficus-ui/native";


const SpinnerComponent = () => {
return (
<SafeAreaBox style={{ flex: 1 }}>
<Text mx="xl" fontSize="4xl">
Spinner component
</Text>
{/* <ExampleSection name="spinner original">
<Box mx="xl" mt="lg">
<Spinner2 />
<Spinner2 color="red" size="small" />
<Spinner2 color="black" size="large" />
</Box>
</ExampleSection> */}
<ExampleSection name="spinner ficus">
<Box mx="xl" mt="lg">
<Spinner />
<Spinner color="red" size="small" />
<Spinner color="black" size="large" />
</Box>
</ExampleSection>
</SafeAreaBox>
);
};

export default SpinnerComponent;
2 changes: 2 additions & 0 deletions apps/examples/app/items-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import BadgeComponent from './components-v2/Badge';
import TouchableHighlightComponent from './components-v2/TouchableHighlight';
import TouchableOpacityComponent from './components-v2/TouchableOpacity';
import TouchableWithoutFeedbackComponent from './components-v2/TouchableWithoutFeedback';
import SpinnerComponent from '@/app/components-v2/Spinner';

type ExampleComponentType = {
onScreenName: string;
Expand All @@ -29,4 +30,5 @@ export const components: ExampleComponentType[] = [
{ navigationPath: 'TouchableHighlight', onScreenName: 'TouchableHighlight', component: TouchableHighlightComponent },
{ navigationPath: 'TouchableOpacity', onScreenName: 'TouchableOpacity', component: TouchableOpacityComponent },
{ navigationPath: 'TouchableWithoutFeedback', onScreenName: 'TouchableWithoutFeedback', component: TouchableWithoutFeedbackComponent },
{ navigationPath: 'Spinner', onScreenName: 'Spinner', component: SpinnerComponent },
];
1 change: 1 addition & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export * from './safe-area-box';
export * from './center';
export * from './badge';
export * from './touchables';
export * from './spinner';

export { ThemeProvider } from '@ficus-ui/theme';
53 changes: 53 additions & 0 deletions packages/components/src/spinner/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useTheme } from '@ficus-ui/theme';

import { type NativeFicusProps, ficus } from '../system';

export interface SpinnerProps extends NativeFicusProps<'ActivityIndicator'> {}

// export const Spinner = ficus('ActivityIndicator'); // something wrong with ficus making color return undefined but size still working correctly

/** ... */
export const Spinner = (props: SpinnerProps) => {
const { theme } = useTheme();
const color = getThemeColor(theme.colors, props.color);

return <ficus.ActivityIndicator {...props} color={color} />;
};

export const getThemeColor = (
themeColors: any,
value: string | any | undefined
): string => {
let colorValueResult: string | String = value as string;

if (themeColors && value) {
// Check if color value is a valid theme color
if (
themeColors.hasOwnProperty(value) &&
(typeof themeColors[value] === 'string' ||
themeColors[value] instanceof String)
) {
const colorValue: string | String = themeColors[value] as string;
return colorValue as string;
}

// If color value contains dots, check into theme sub objects if it's a valid theme color
if (value?.includes('.')) {
const keyParts = value.split('.');
let subPropertyValue: any = themeColors;
for (const part of keyParts) {
if (subPropertyValue && part) {
subPropertyValue = subPropertyValue[part];
}
}
if (
typeof subPropertyValue === 'string' ||
subPropertyValue instanceof String
) {
colorValueResult = subPropertyValue;
}
}
}

return colorValueResult as string;
};
26 changes: 26 additions & 0 deletions packages/components/src/spinner/spinner.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

import { render } from '@testing-library/react-native';

import { Spinner } from '.';

describe('ActivityIndicator Component', () => {
it('renders with default props', () => {
const { getByTestId } = render(<Spinner testID="loading-indicator" />);
expect(getByTestId('loading-indicator')).toBeTruthy();
});

it('applies custom color', () => {
const { getByTestId } = render(
<Spinner testID="loading-indicator" color="red" />
);
expect(getByTestId('loading-indicator').props.color).toBe('red');
});

it('applies custom size', () => {
const { getByTestId } = render(
<Spinner testID="loading-indicator" size="large" />
);
expect(getByTestId('loading-indicator').props.size).toBe('large');
});
});
2 changes: 2 additions & 0 deletions packages/components/src/system/base-elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
TouchableOpacity as RNTouchableOpacity,
TouchableWithoutFeedback as RNTouchableWithoutFeedback,
View as RNView,
ActivityIndicator as RNActivityIndicator,
} from 'react-native';

/**
Expand All @@ -21,6 +22,7 @@ export const baseRNElements = {
TouchableHighlight: RNTouchableHighlight,
TouchableOpacity: RNTouchableOpacity,
TouchableWithoutFeedback: RNTouchableWithoutFeedback,
ActivityIndicator: RNActivityIndicator,
} as const;

export type BaseRNElements = keyof typeof baseRNElements;
Loading