Skip to content

Instantly share code, notes, and snippets.

@yano3nora
Last active March 29, 2023 09:52
Show Gist options
  • Save yano3nora/6f3c1791ac1a1109900fce29dec62c17 to your computer and use it in GitHub Desktop.
Save yano3nora/6f3c1791ac1a1109900fce29dec62c17 to your computer and use it in GitHub Desktop.
[js: striped-list] list component by render prop pattern.
import React, { ReactNode } from 'react'
import { Box, Divider, VStack } from '@chakra-ui/layout'
import { ChakraProps } from '@chakra-ui/system'
/**
* ↓ みたいなやつ作りたい時用
*
* item1
* -------
* item2
* -------
* item3
*
* @exmaple
* <StripedListByEntities entities={users} keyProp={'id'}>
* {user => <div>{user.name}</div>}
* </StripedList>
*/
export const StripedListByEntities = <T, >({
entities,
keyProp,
style,
children,
}: {
entities: T[]
keyProp?: keyof T
style?: ChakraProps
children: (entity: T) => ReactNode
}) => <VStack spacing={0} width={'100%'}>
{entities.map((entity, idx) => <VStack
key={
keyProp &&
entity instanceof Object &&
Object.hasOwn(entity, keyProp)
? String(entity[keyProp])
: idx // key 指定がない or primitive array なら index にしとく
}
width={'100%'}
spacing={0}
>
<Box width={'100%'} py={3} {...style}>
{children(entity)}
</Box>
{
(idx + 1) !== entities.length &&
<Divider borderColor={'gray.400'} width={'90%'} />
}
</VStack>)}
</VStack>
import React, { ReactNode } from 'react'
import { Box, Divider, VStack } from '@chakra-ui/layout'
import { BorderProps, ChakraProps } from '@chakra-ui/system'
/**
* ↓ みたいなやつ作りたい時用
* -------
* item1
* -------
* item2
* -------
* item3
* -------
*
* @exmaple
* <StripedList>
* <HStack>{...}</HStack>
* </StripedList>
*/
export const StripedList = (props: ChakraProps & {
children: ReactNode
innerStyles?: ChakraProps
borderStyles?: BorderProps
borderTrimmed?: true
}) => {
const {
children,
innerStyles,
borderStyles,
borderTrimmed,
...styles
} = props
const nodes = React.Children.toArray(children)
const Border = <Divider borderColor={'gray.300'} {...borderStyles} />
return <VStack spacing={0} width={'100%'} {...styles}>
{nodes.map((node, idx) => <VStack
key={idx}
width={'100%'}
spacing={0}
>
{
idx === 0 &&
!borderTrimmed &&
Border
}
<Box width={'100%'} py={3} {...innerStyles}>
{node}
</Box>
{
(
((idx + 1) !== nodes.length) || // not last
((idx + 1) === nodes.length && !borderTrimmed) // last & no trim
) &&
Border
}
</VStack>)}
</VStack>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment