Skip to content
Merged
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
10 changes: 9 additions & 1 deletion packages/docs/docs/flex/props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
sidebar_position: 2
---

import PlatformBadges from '@site/src/components/PlatformBadges';

# Props

:::info
Expand Down Expand Up @@ -385,14 +387,20 @@ Opacity to which the pressed item is animated when active.

---

### activeItemShadowOpacity
### activeItemShadowOpacity<PlatformBadges platforms={['ios', 'web']} />

Shadow opacity of the active item.

| type | default | required |
| -------------------- | ------- | -------- |
| `Animatable<number>` | 0.2 | NO |

:::info

If you want to use shadows on **Android**, please refer to the [Custom Shadow](/grid/examples/custom-shadow) example.

:::

---

### inactiveItemOpacity
Expand Down
96 changes: 96 additions & 0 deletions packages/docs/docs/grid/examples/custom-shadow.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
sidebar_position: 9
description: ''
---

# Custom Shadow

## Description

This example demonstrates how to create a **custom shadow** for the active item during drag. By disabling the default shadow with `activeItemShadowOpacity={0}` and using the [useItemContext](/hooks/useItemContext) hook, you can animate the `box-shadow` property of the item based on the activation animation progress.

This is particularly useful when you want to add shadows on **Android**, where shadows are not supported by default and must be implemented by the user.

## Source Code

```tsx
import { memo, useCallback } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Animated, {
interpolateColor,
useAnimatedStyle
} from 'react-native-reanimated';
import type { SortableGridRenderItem } from 'react-native-sortables';
import Sortable, { useItemContext } from 'react-native-sortables';

const DATA = Array.from({ length: 12 }, (_, index) => `Item ${index + 1}`);

export default function Example() {
const renderItem = useCallback<SortableGridRenderItem<string>>(
({ item }) => <GridItem item={item} />,
[]
);

return (
<View style={styles.container}>
<Sortable.Grid
// Disable default shadow as we will apply our
// box-shadow in the item component
activeItemShadowOpacity={0}
columnGap={10}
columns={3}
data={DATA}
renderItem={renderItem}
rowGap={10}
/>
</View>
);
}

const GridItem = memo(function GridItem({ item }: { item: string }) {
const { activationAnimationProgress } = useItemContext();

const animatedStyle = useAnimatedStyle(() => {
const color = interpolateColor(
activationAnimationProgress.value,
[0, 1],
['transparent', '#1a433f']
);
return {
boxShadow: `0 5px 10px ${color}`
};
});

return (
<Animated.View style={[styles.card, animatedStyle]}>
<Text style={styles.text}>{item}</Text>
</Animated.View>
);
});

const styles = StyleSheet.create({
card: {
alignItems: 'center',
backgroundColor: '#36877F',
borderRadius: 10,
height: 100,
justifyContent: 'center'
},
container: {
padding: 16
},
text: {
color: 'white',
fontWeight: 'bold'
}
});
```

## Result

import customShadowVideoAndroid from '@site/static/video/grid-custom-shadow-android.mp4';
import customShadowVideoIOS from '@site/static/video/grid-custom-shadow-ios.mp4';

| Android | iOS |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| <div style={{ textAlign: 'center' }}><video autoPlay loop muted width="100%" style={{ maxWidth: '300px' }} src={customShadowVideoAndroid} /></div> | <div style={{ textAlign: 'center' }}><video autoPlay loop muted width="100%" style={{ maxWidth: '300px' }} src={customShadowVideoIOS} /></div> |
10 changes: 9 additions & 1 deletion packages/docs/docs/grid/props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
sidebar_position: 2
---

import PlatformBadges from '@site/src/components/PlatformBadges';

# Props

:::info
Expand Down Expand Up @@ -253,14 +255,20 @@ Opacity to which the pressed item is animated when active.

---

### activeItemShadowOpacity
### activeItemShadowOpacity<PlatformBadges platforms={['ios', 'web']} />

Shadow opacity of the active item.

| type | default | required |
| -------------------- | ------- | -------- |
| `Animatable<number>` | 0.2 | NO |

:::info

If you want to use shadows on **Android**, please refer to the [Custom Shadow](/grid/examples/custom-shadow) example.

:::

---

### inactiveItemOpacity
Expand Down
75 changes: 0 additions & 75 deletions packages/docs/src/components/HomepageFeatures/index.tsx

This file was deleted.

11 changes: 0 additions & 11 deletions packages/docs/src/components/HomepageFeatures/styles.module.css

This file was deleted.

53 changes: 53 additions & 0 deletions packages/docs/src/components/PlatformBadges/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { clsx } from 'clsx';
import { type PropsWithChildren, useMemo } from 'react';

import styles from './styles.module.css';

export type Platform = 'android' | 'ios' | 'web';

type PlatformBadgeProps = PropsWithChildren<{
platform: Platform;
}>;

function PlatformBadge({ children, platform }: PlatformBadgeProps) {
const platformInfo = useMemo(() => {
switch (platform) {
case 'android':
return {
className: styles.android,
color: '#3DDC84',
label: 'Android'
};
case 'ios':
return {
className: styles.ios,
color: '#007AFF',
label: 'iOS'
};
case 'web':
return {
className: styles.web,
color: '#FF6B35',
label: 'Web'
};
}
}, [platform]);

return (
<span className={clsx(styles.badge, platformInfo?.className)}>
{children ?? platformInfo.label}
</span>
);
}

function PlatformBadges({ platforms }: { platforms: Array<Platform> }) {
return (
<div className={styles.badgeContainer}>
{platforms.map(platform => (
<PlatformBadge key={platform} platform={platform} />
))}
</div>
);
}

export default PlatformBadges;
58 changes: 58 additions & 0 deletions packages/docs/src/components/PlatformBadges/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
.badge {
display: inline-flex;
align-items: center;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
font-weight: 600;
line-height: 1;
border-radius: 9999px;
text-transform: uppercase;
letter-spacing: 0.025em;
margin: 0 0.125rem;
}

.badgeContainer {
display: inline-flex;
flex-wrap: wrap;
gap: 0.125rem;
margin: 0 0 0 0.5rem;
vertical-align: middle;
transform: translateY(-0.1em);
}

.ios {
background-color: rgba(0, 122, 255, 0.15);
color: #007aff;
border: 1px solid rgba(0, 122, 255, 0.25);
}

.android {
background-color: rgba(61, 220, 132, 0.15);
color: #3ddc84;
border: 1px solid rgba(61, 220, 132, 0.25);
}

.web {
background-color: rgba(255, 107, 53, 0.15);
color: #ff6b35;
border: 1px solid rgba(255, 107, 53, 0.25);
}

/* Dark mode support */
[data-theme='dark'] .ios {
background-color: rgba(0, 122, 255, 0.25);
color: #5ac8fa;
border-color: rgba(0, 122, 255, 0.4);
}

[data-theme='dark'] .android {
background-color: rgba(61, 220, 132, 0.25);
color: #7cff9b;
border-color: rgba(61, 220, 132, 0.4);
}

[data-theme='dark'] .web {
background-color: rgba(255, 107, 53, 0.25);
color: #ff8a65;
border-color: rgba(255, 107, 53, 0.4);
}
4 changes: 2 additions & 2 deletions packages/docs/src/components/TabView/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { clsx } from 'clsx';
import type { ReactElement } from 'react';
import type React from 'react';
import type { ReactElement } from 'react';
import { Children, useMemo, useState } from 'react';

import styles from './styles.module.css';

type TabsProps = {
children: Array<React.ReactElement<TabItemProps>>;
children: Array<ReactElement<TabItemProps>>;
};

function TabView({ children }: TabsProps) {
Expand Down
Binary file not shown.
Binary file not shown.
4 changes: 2 additions & 2 deletions packages/docs/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12766,11 +12766,11 @@ __metadata:

"typescript@patch:typescript@npm%3A^5.8.3#optional!builtin<compat/typescript>":
version: 5.8.3
resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin<compat/typescript>::version=5.8.3&hash=379a07"
resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin<compat/typescript>::version=5.8.3&hash=5786d5"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/92ea03509e06598948559ddcdd8a4ae5a7ab475766d5589f1b796f5731b3d631a4c7ddfb86a3bd44d58d10102b132cd4b4994dda9b63e6273c66d77d6a271dbd
checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb
languageName: node
linkType: hard

Expand Down
Loading
Loading