mirror of
https://github.com/wavetermdev/docusaurus-og.git
synced 2026-08-05 13:46:35 -07:00
refactor: extract Grid scroll buttons into a reusable component, ScrollButtons
This commit is contained in:
@@ -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;
|
||||
}
|
||||
`)}
|
||||
`
|
||||
|
||||
+57
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+85
@@ -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'
|
||||
Reference in New Issue
Block a user