Skip to content

Commit

Permalink
feat: apply rtl to carousel
Browse files Browse the repository at this point in the history
  • Loading branch information
bang9 committed Nov 25, 2024
1 parent 51f43d4 commit 67972a7
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 17 deletions.
25 changes: 17 additions & 8 deletions src/components/messages/CarouselMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { SnapCarousel } from '../ui/SnapCarousel';
const listPadding = 16;
const avatarSize = 28;
const avatarMargin = 8;
const leftMargin = avatarSize + avatarMargin + listPadding;
const startMargin = avatarSize + avatarMargin + listPadding;

const BodyWrapper = styled.div({
display: 'flex',
Expand Down Expand Up @@ -49,7 +49,7 @@ const Image = styled.img`
background-color: ${({ theme }) => theme.bgColor.carouselItem};
`;

const Button = styled.button<{ direction: 'left' | 'right' }>(({ theme, direction }) => ({
const Button = styled.button<{ direction: 'start' | 'end' }>(({ theme, direction }) => ({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
Expand All @@ -58,14 +58,23 @@ const Button = styled.button<{ direction: 'left' | 'right' }>(({ theme, directio
transform: 'translateY(-50%)',
border: 'none',
cursor: 'pointer',
borderRadius: direction === 'right' ? '100px 0px 0px 100px' : '0px 100px 100px 0px',
padding: direction === 'right' ? '8px 8px 8px 12px' : '8px 12px 8px 8px',
borderStartStartRadius: direction === 'start' ? 0 : 100,
borderStartEndRadius: direction === 'end' ? 0 : 100,
borderEndStartRadius: direction === 'start' ? 0 : 100,
borderEndEndRadius: direction === 'end' ? 0 : 100,
paddingTop: 8,
paddingBottom: 8,
paddingInlineStart: direction === 'end' ? 12 : 8,
paddingInlineEnd: direction === 'start' ? 12 : 8,
backgroundColor: theme.bgColor.carouselButton,
boxShadow:
'0px 8px 10px 1px rgba(13, 13, 13, 0.12), 0px 3px 14px 2px rgba(13, 13, 13, 0.08), 0px 3px 5px -3px rgba(13, 13, 13, 0.04)',
'&:hover': {
backgroundColor: theme.bgColor.hover.carouselButton,
},
'[dir=rtl] & svg': {
transform: 'scaleX(-1)',
},
}));

type Props = {
Expand All @@ -85,20 +94,20 @@ export const CarouselMessage = ({ streaming, textBody, streamingBody, items }: P

return (
<SnapCarousel
startPadding={leftMargin}
startPadding={startMargin}
endPadding={listPadding}
gap={avatarMargin}
style={{ marginInlineStart: -leftMargin, marginInlineEnd: -listPadding }}
style={{ marginInlineStart: -startMargin, marginInlineEnd: -listPadding }}
renderButtons={({ activeIndex, onClickPrev, onClickNext }) =>
shouldRenderButtons && (
<>
{activeIndex !== 0 && (
<Button style={{ insetInlineStart: -leftMargin }} onClick={onClickPrev} direction={'left'}>
<Button style={{ insetInlineStart: -startMargin }} onClick={onClickPrev} direction={'start'}>
<ChevronLeft width={24} height={24} fill={theme.bgColor.carouselButtonIcon} />
</Button>
)}
{activeIndex !== items.length - 1 && (
<Button style={{ insetInlineEnd: -listPadding }} onClick={onClickNext} direction={'right'}>
<Button style={{ insetInlineEnd: -listPadding }} onClick={onClickNext} direction={'end'}>
<ChevronRight width={24} height={24} fill={theme.bgColor.carouselButtonIcon} />
</Button>
)}
Expand Down
16 changes: 7 additions & 9 deletions src/components/ui/SnapCarousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Container = styled.div({
overflowY: 'scroll',
gap: 12,
scrollPadding: 0,
paddingLeft: 0,
paddingInlineStart: 0,
scrollbarWidth: 'none',
userSelect: 'none',
'::-webkit-scrollbar': {
Expand Down Expand Up @@ -58,25 +58,23 @@ export const SnapCarousel = ({
}: SnapCarouselProps) => {
const ref = useRef<HTMLDivElement>(null);
const [activeIndex, setActiveState] = useState(0);
const itemLength = React.Children.toArray(children).length;

const direction = (ref.current ? getComputedStyle(ref.current).direction : 'ltr') as 'rtl' | 'ltr';
const itemLength = React.Children.toArray(children).length;
const itemWidth = useMemo(() => {
const total = ref.current?.scrollWidth ?? 0;
return (total - (startPadding + endPadding + gap * (itemLength - 1))) / itemLength;
}, [ref.current?.scrollWidth, itemLength, gap, startPadding, endPadding]);

const onScroll = (e: React.UIEvent<HTMLDivElement>) => {
const idx = Math.round(e.currentTarget.scrollLeft / itemWidth);
const idx = Math.round(e.currentTarget.scrollLeft / itemWidth) * (direction === 'ltr' ? 1 : -1);
if (idx !== activeIndex) setActiveState(idx);
};

const scrollTo = (index: number) => {
if (ref.current) {
const nextIdx = Math.min(Math.max(0, index), itemLength - 1);
ref.current.scroll({
left: nextIdx * itemWidth,
behavior: 'smooth',
});
ref.current.scroll({ left: nextIdx * itemWidth * (direction === 'ltr' ? 1 : -1), behavior: 'smooth' });
}
};

Expand All @@ -88,8 +86,8 @@ export const SnapCarousel = ({
style={{
gap,
scrollPadding: startPadding,
paddingLeft: startPadding,
paddingRight: endPadding,
paddingInlineStart: startPadding,
paddingInlineEnd: endPadding,
...style,
}}
>
Expand Down

0 comments on commit 67972a7

Please sign in to comment.