diff --git a/src/Stack/README.stories.mdx b/src/Stack/README.stories.mdx index 0c2091a3..73b1c0cc 100644 --- a/src/Stack/README.stories.mdx +++ b/src/Stack/README.stories.mdx @@ -14,14 +14,16 @@ import Stack, {StackWrapper, StackItem} from './'; import Stack from 'base5-ui/Stack'; ``` -Control vertical spacing between Stack items. Supports all `Box` style props. +Control vertical spacing and dividers between Stack items. Supports all `Box` style props. -## Examples +## Spacing + +Use the `spacing` prop with responsive theme tokens to control the distance between each list item. Home Projects + Pricing + About us + + )} + + + +## Dividers + +Use the `withDividers` prop to add a simple divider between each list item. + +> Note that this also adds `overflow: hidden` to the `Stack` container. + + + + {props => ( + + Home + Projects + Pricing About us )} @@ -70,7 +101,12 @@ The following list has a third list item that will be hidden on larger screens. {props => ( @@ -101,7 +137,12 @@ Instead of using the `Hidden` component to responsively hide items, you can pass {props => ( diff --git a/src/Stack/index.js b/src/Stack/index.js index ccab7d1a..d4144f06 100644 --- a/src/Stack/index.js +++ b/src/Stack/index.js @@ -4,9 +4,10 @@ import PropTypes from 'prop-types'; import {getSpacing, createStyleFunction} from '../utils'; import Box from '../Box'; +import Divider from '../Divider'; import Hidden from '../Hidden'; -export const spacingCompensationProp = createStyleFunction([ +const spacingCompensationProp = createStyleFunction([ { styleProp: 'compensateSpacing', properties: ['marginBottom'], @@ -14,6 +15,21 @@ export const spacingCompensationProp = createStyleFunction([ }, ]); +const dividerCompensationProp = createStyleFunction([ + { + styleProp: 'compensateSpacing', + properties: ['marginBottom'], + getValue: (value, theme) => { + const spacing = getSpacing(value, theme); + if (Number(spacing) === 0) { + return '-1px'; + } else { + return `calc(-${spacing} * 2 - 1px)`; + } + }, + }, +]); + /** * Using a pseudo element to compensate for the spacing * between items (instead of negative margin) to allow @@ -21,14 +37,22 @@ export const spacingCompensationProp = createStyleFunction([ * E.g., if a negative margin-top was used instead, it would * clash with the `mt` prop. */ + const Wrapper = styled(Box).withConfig({ shouldForwardProp: prop => prop !== 'compensateSpacing', })` + ${p => + p.withDividers && + ` + overflow: hidden; + `} + &::before { content: ''; display: block; height: 0; - ${spacingCompensationProp} + ${p => + p.withDividers ? dividerCompensationProp : spacingCompensationProp} } `; @@ -49,12 +73,20 @@ function getHiddenChildProps(child) { } else return null; } -function Stack({children, spacing, breakpoints, as, ...otherProps}) { +function Stack({ + children, + spacing, + withDividers, + breakpoints, + as, + ...otherProps +}) { const [wrapperAs, itemAs] = getRoles(as); return ( + {withDividers && } {hiddenChildProps ? hiddenChildProps.children : child} ); @@ -102,6 +135,10 @@ Stack.propTypes = { PropTypes.number, PropTypes.array, ]), + /** + * Add dividers between each Stack item + */ + withDividers: PropTypes.bool, /** * Breakpoints to use when responsive spacing values are provided */ @@ -120,7 +157,10 @@ Stack.propTypes = { const StandaloneStackContext = createContext(); const StackWrapper = forwardRef( - ({children, as, spacing, breakpoints, ...otherProps}, ref) => { + ( + {children, as, spacing, withDividers, breakpoints, ...otherProps}, + ref + ) => { const [wrapperAs, itemAs] = getRoles(as); return ( {children} @@ -147,7 +188,9 @@ const StackItem = forwardRef( {children, hiddenAbove, hiddenBelow, allowUnknownProps, ...otherProps}, ref ) => { - const {as, spacing, breakpoints} = useContext(StandaloneStackContext); + const {as, spacing, withDividers, breakpoints} = useContext( + StandaloneStackContext + ); const Component = hiddenAbove || hiddenBelow ? Hidden : Box; @@ -161,6 +204,7 @@ const StackItem = forwardRef( above={hiddenAbove} breakpoints={breakpoints} > + {withDividers && } {children} );