refactor: extract Grid scroll buttons into a reusable component, ScrollButtons

This commit is contained in:
Hossein Mehrabi
2023-12-14 18:09:42 +03:30
parent ab6a5a8048
commit 472799d743
4 changed files with 152 additions and 122 deletions
@@ -1,15 +1,10 @@
import {
ChevronLeftIcon,
ChevronRightIcon,
IconButton,
IconButtonGroup,
THEME_BREAKPOINTS,
} from '@acid-info/lsd-react'
import { THEME_BREAKPOINTS } from '@acid-info/lsd-react'
import { css } from '@emotion/react'
import styled from '@emotion/styled'
import clsx from 'clsx'
import React, { useRef } from 'react'
import { lsdUtils } from '../../../lib/lsd.utils'
import { ScrollButtons } from '../ScrollButtons'
import { GridItem } from './GridItem'
export type GridProps = React.ComponentProps<typeof GridRoot> & {
@@ -29,62 +24,17 @@ export const Grid: { Item: typeof GridItem } & React.FC<GridProps> = ({
}) => {
const ref = useRef<HTMLDivElement>(null)
const scroll = (direction: -1 | 1) => {
const el = ref.current
if (!el) return
const itemWidth = el.children[0]?.getBoundingClientRect?.()?.width ?? 236
el.scrollTo({
behavior: 'smooth',
left:
el.scrollLeft +
(el.getBoundingClientRect()?.width - itemWidth) * direction,
})
}
return (
<GridRoot {...props} className={clsx(props.className, 'mdx-grid')}>
<div className="mdx-grid__actions">
{actions}
<div
className={clsx(
'mdx-grid__scroll',
spacingButtons && 'mdx-grid__scroll--spacing-buttons',
)}
>
<IconButtonGroup size="small" color="primary">
<IconButton
className={clsx(
'mdx-grid__scroll-button',
leftLabel?.length && 'mdx-grid__scroll-button--with-label',
)}
size="small"
onClick={scroll.bind(null, -1)}
>
<ChevronLeftIcon />
{leftLabel.length ? (
<span className="mdx-grid__scroll-button-label">
{leftLabel}
</span>
) : null}
</IconButton>
<IconButton
className={clsx(
'mdx-grid__scroll-button',
rightLabel?.length && 'mdx-grid__scroll-button--with-label',
)}
size="small"
onClick={scroll.bind(null, +1)}
>
{rightLabel.length ? (
<span className="mdx-grid__scroll-button-label">
{rightLabel}
</span>
) : null}
<ChevronRightIcon />
</IconButton>
</IconButtonGroup>
</div>
<ScrollButtons
containerRef={ref}
className="mdx-grid__scroll"
leftLabel={leftLabel}
rightLabel={rightLabel}
spacing={spacingButtons ? 'spaced' : 'grouped'}
/>
</div>
<div ref={ref} className={clsx('mdx-grid__content', 'hidden-scrollbar')}>
{children}
@@ -113,26 +63,6 @@ const GridRoot = styled.div<{
.mdx-grid__scroll {
display: flex;
flex-direction: row;
gap: 0 1rem;
margin-left: auto;
}
.mdx-grid__scroll--spacing-buttons {
width: 100%;
> div {
justify-content: space-between;
width: 100%;
}
> div > button:not(:last-child) {
border-right: 1px solid rgb(var(--lsd-border-primary)) !important;
}
}
.mdx-grid__scroll-button {
display: flex;
}
.mdx-grid__content {
@@ -211,47 +141,4 @@ const GridRoot = styled.div<{
`}
`)
})}
${(props) =>
lsdUtils.responsive(
props.theme as any,
'md',
'up',
)(css`
.mdx-grid__scroll-button--with-label {
width: auto;
min-width: 83px;
padding: 5px 11px 5px 9px;
gap: 12px;
&:first-of-type {
justify-content: flex-start;
}
&:last-of-type {
justify-content: flex-start;
}
}
`)}
${(props) =>
lsdUtils.responsive(
props.theme as any,
'sm',
'down',
)(css`
.mdx-grid__scroll {
& > div {
justify-content: flex-end;
> button:not(:last-child) {
border-right: none !important;
}
}
}
.mdx-grid__scroll-button-label {
display: none;
}
`)}
`
@@ -0,0 +1,57 @@
@use '../../../css/utils';
@use '../../../css/lsd';
.mdx-scroll-buttons {
width: 100%;
> div {
width: 100%;
display: flex;
flex-direction: row;
justify-content: flex-end;
}
}
@include utils.responsive('md', 'up') {
.mdx-scroll-buttons__button--with-label {
width: auto !important;
min-width: 83px;
padding: 5px 11px 5px 9px !important;
gap: 12px;
&:first-of-type {
justify-content: flex-start;
}
&:last-of-type {
justify-content: flex-start;
}
}
.mdx-scroll-buttons--spaced {
& > div {
gap: 0 1rem;
justify-content: space-between;
& > button:not(:last-child) {
border-right: 1px solid rgb(var(--lsd-border-primary)) !important;
}
}
}
}
@include utils.responsive('md', 'down') {
.mdx-scroll-buttons {
& > div {
justify-content: flex-end;
> button:not(:last-child) {
border-right: none !important;
}
}
.mdx-scroll-buttons__label {
display: none;
}
}
}
@@ -0,0 +1,85 @@
import {
ChevronLeftIcon,
ChevronRightIcon,
IconButton,
IconButtonGroup,
} from '@acid-info/lsd-react'
import clsx from 'clsx'
import React from 'react'
import './ScrollButtons.scss'
export type ScrollButtonsProps = React.HTMLProps<HTMLDivElement> & {
containerId?: string
containerRef?: React.RefObject<HTMLElement>
leftLabel?: string
rightLabel?: string
spacing?: 'spaced' | 'grouped'
}
export const ScrollButtons: React.FC<ScrollButtonsProps> = ({
leftLabel,
rightLabel,
containerRef,
containerId,
spacing = 'grouped',
...props
}) => {
const scroll = (direction: -1 | 1) => {
const el = containerRef
? containerRef.current
: document.querySelector(`#${containerId}`)
if (!el) return
const itemWidth = el.children[0]?.getBoundingClientRect?.()?.width ?? 236
el.scrollTo({
behavior: 'smooth',
left:
el.scrollLeft +
(el.getBoundingClientRect()?.width - itemWidth) * direction,
})
}
return (
<div
{...props}
className={clsx(
props.className,
'mdx-scroll-buttons',
spacing === 'spaced' && 'mdx-scroll-buttons--spaced',
)}
>
<IconButtonGroup size="small" color="primary">
<IconButton
className={clsx(
'mdx-scroll-buttons__button',
leftLabel &&
leftLabel.length > 0 &&
'mdx-scroll-buttons__button--with-label',
)}
size="small"
onClick={scroll.bind(null, -1)}
>
<ChevronLeftIcon />
{leftLabel && leftLabel.length > 0 && (
<span className="mdx-scroll-buttons__label">{leftLabel}</span>
)}
</IconButton>
<IconButton
className={clsx(
'mdx-scroll-buttons__button',
rightLabel &&
rightLabel.length &&
'mdx-scroll-buttons__button--with-label',
)}
size="small"
onClick={scroll.bind(null, +1)}
>
{rightLabel && rightLabel.length > 0 && (
<span className="mdx-scroll-buttons__label">{rightLabel}</span>
)}
<ChevronRightIcon />
</IconButton>
</IconButtonGroup>
</div>
)
}
@@ -0,0 +1 @@
export * from './ScrollButtons'