-
Notifications
You must be signed in to change notification settings - Fork 53
feat: Flex component #802
feat: Flex component #802
Changes from all commits
3da9172
9c93a0f
711e5bb
8145e7e
ab39fc4
2970fa3
9a3d819
6f4b06a
816f56b
c36771a
ddc2eb7
f0eb6a3
41d7750
86d9625
9dbd7ea
cad2801
26309e3
e1ba117
d7fbcf6
b0d6311
0520069
101f03c
3819197
8115ad2
9248534
4bb83c1
52c4e33
911eca2
2d6e7a2
10ab8b7
447f745
bcd9929
e0a4ea3
31f1bd4
5d0682e
81a975b
62c2000
fc1582e
e26502f
7797fc1
b3f2e86
c87230f
daa1601
8dab420
5f1658b
e99c27a
1a37491
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import * as React from 'react' | ||
import { Flex, Segment } from '@stardust-ui/react' | ||
|
||
const FlexExampleColumns = () => ( | ||
<> | ||
<Flex gap="gap.small" padding="padding.medium"> | ||
<Flex.Item size="size.half"> | ||
<Segment content="1/2" /> | ||
</Flex.Item> | ||
|
||
<Flex.Item size="size.half"> | ||
<Segment content="1/2" /> | ||
</Flex.Item> | ||
</Flex> | ||
|
||
<Flex gap="gap.small" padding="padding.medium"> | ||
<Flex.Item size="size.quarter"> | ||
<Segment content="1/4" /> | ||
</Flex.Item> | ||
|
||
<Flex.Item size="size.half"> | ||
<Segment content="1/2" /> | ||
</Flex.Item> | ||
|
||
<Flex.Item size="size.quarter"> | ||
<Segment content="1/4" /> | ||
</Flex.Item> | ||
</Flex> | ||
|
||
<Flex gap="gap.small" padding="padding.medium" style={{ minHeight: 200 }}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, actually, it was - and the main reason for not doing it (for now, at least) is that Also, note that if Flex needs to be provided with some height while being part of some other component, this will be done by styles, not by the props API: renderComponent = ({ ..., ElementType, styles }) => {
<ElementType>
<Flex styles={styles.flex} >
....
</Flex>
</ElementType>
}
/// myComponentStyles.js
{
root: ...
flex: {
height: '200px'
}
} |
||
<Flex.Item size="size.half"> | ||
<Segment content="Full-height, even when my content doesn't fill the space." /> | ||
</Flex.Item> | ||
|
||
<Flex.Item size="size.half"> | ||
<Segment content="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum mollis velit non gravida venenatis. Praesent consequat lectus purus, ut scelerisque velit condimentum eu. Maecenas sagittis ante ut turpis varius interdum. Quisque tellus ipsum, eleifend non ipsum id, suscipit ultricies neque." /> | ||
</Flex.Item> | ||
</Flex> | ||
</> | ||
) | ||
|
||
export default FlexExampleColumns |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import * as React from 'react' | ||
import { Flex, Input, Button, Label } from '@stardust-ui/react' | ||
|
||
const FlexExampleInput = () => ( | ||
<Flex gap="gap.medium" debug> | ||
<Flex.Item grow> | ||
<Flex> | ||
<Label | ||
icon="plane" | ||
styles={{ background: 'darkgrey', height: 'auto', padding: '0 15px' }} | ||
/> | ||
|
||
<Flex.Item grow> | ||
<Input placeholder="Enter your flight #" fluid /> | ||
</Flex.Item> | ||
</Flex> | ||
</Flex.Item> | ||
|
||
<Button content="Load" /> | ||
</Flex> | ||
) | ||
|
||
export default FlexExampleInput |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import * as React from 'react' | ||
import { Flex, Segment } from '@stardust-ui/react' | ||
|
||
const FlexExampleItemsAlignment = () => ( | ||
<Flex column gap="gap.large" hAlign="center" vAlign="center" debug> | ||
{[ | ||
[ | ||
{ hAlign: 'start', vAlign: 'start' }, | ||
{ hAlign: 'start', vAlign: 'center' }, | ||
{ hAlign: 'start', vAlign: 'end' }, | ||
], | ||
[ | ||
{ hAlign: 'center', vAlign: 'start' }, | ||
{ hAlign: 'center', vAlign: 'center' }, | ||
{ hAlign: 'center', vAlign: 'end' }, | ||
], | ||
[ | ||
{ hAlign: 'end', vAlign: 'start' }, | ||
{ hAlign: 'end', vAlign: 'center' }, | ||
{ hAlign: 'end', vAlign: 'end' }, | ||
], | ||
].map(rowOfAlignmentProps => ( | ||
<Flex gap="gap.large"> | ||
{rowOfAlignmentProps.map((alignmentProps: any) => ( | ||
<Flex inline {...alignmentProps} style={{ width: '100px', height: '100px' }} debug> | ||
<Segment styles={{ width: '30px', height: '30px' }} /> | ||
</Flex> | ||
))} | ||
</Flex> | ||
))} | ||
</Flex> | ||
) | ||
|
||
export default FlexExampleItemsAlignment |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import * as React from 'react' | ||
import { Flex, Image, Text, Header } from '@stardust-ui/react' | ||
|
||
const FlexExampleMediaCard = () => ( | ||
<Flex gap="gap.medium" padding="padding.medium" debug> | ||
<Flex.Item size="size.medium"> | ||
<div style={{ position: 'relative' }}> | ||
<Image fluid src="public/images/avatar/large/ade.jpg" /> | ||
</div> | ||
</Flex.Item> | ||
|
||
<Flex.Item grow> | ||
<Flex column gap="gap.small" vAlign="stretch"> | ||
<Flex space="between"> | ||
<Header as="h3" content="LOREM IPSUM" /> | ||
<Text as="pre" content="Oct 24th, 00:01" /> | ||
</Flex> | ||
|
||
<Text content="Man braid iPhone locavore hashtag pop-up, roof party forage heirloom chillwave brooklyn yr 8-bit gochujang blog." /> | ||
|
||
<Flex.Item push> | ||
<Text as="pre" content="COPYRIGHT: Stardust-UI Inc." /> | ||
</Flex.Item> | ||
</Flex> | ||
</Flex.Item> | ||
</Flex> | ||
) | ||
|
||
export default FlexExampleMediaCard |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import * as React from 'react' | ||
import { Flex, Segment } from '@stardust-ui/react' | ||
|
||
const FlexExampleMixedAlignment = () => ( | ||
<Flex gap="gap.small" hAlign="center" vAlign="center" debug> | ||
<Flex.Item align="start" size="size.small"> | ||
<Segment content="This cell should be top aligned." /> | ||
</Flex.Item> | ||
|
||
<Flex.Item align="stretch" size="size.small"> | ||
<Segment content="Curabitur pulvinar dolor lectus, quis porta turpis ullamcorper nec. Quisque eget varius turpis, quis iaculis nibh. Ut interdum ligula id metus hendrerit cursus. Integer eu leo felis. Aenean commodo ultrices nunc, sit amet blandit elit gravida in. Sed est ligula, ornare ac nisi adipiscing, iaculis facilisis tellus." /> | ||
</Flex.Item> | ||
|
||
<Flex.Item align="center" size="size.small"> | ||
<Segment content="This cell should be center-aligned." /> | ||
</Flex.Item> | ||
|
||
<Flex.Item align="end" size="size.small"> | ||
<Segment content="This cell should be bottom-aligned." /> | ||
</Flex.Item> | ||
</Flex> | ||
) | ||
|
||
export default FlexExampleMixedAlignment |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import * as React from 'react' | ||
import { Flex, Button } from '@stardust-ui/react' | ||
|
||
const FlexExampleNavMenu = () => ( | ||
<Flex gap="gap.small" debug> | ||
<Button content="Logo" icon="chess rook" /> | ||
|
||
<Flex.Item push> | ||
<Button content="Page 1" /> | ||
</Flex.Item> | ||
|
||
<Button content="Page 2" /> | ||
<Button content="Page 3" /> | ||
</Flex> | ||
) | ||
|
||
export default FlexExampleNavMenu |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import * as React from 'react' | ||
import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample' | ||
import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection' | ||
|
||
const Types = () => ( | ||
<ExampleSection title="Types"> | ||
<ComponentExample | ||
kuzhelov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
title="Media Card" | ||
description="Flex items alignment options." | ||
examplePath="components/Flex/Types/FlexExampleMediaCard" | ||
/> | ||
<ComponentExample | ||
title="Input" | ||
description="Flex items alignment options." | ||
examplePath="components/Flex/Types/FlexExampleInput" | ||
/> | ||
<ComponentExample | ||
title="Nav Menu" | ||
description="Flex items alignment options." | ||
examplePath="components/Flex/Types/FlexExampleNavMenu" | ||
/> | ||
<ComponentExample | ||
title="Items Alignment" | ||
description="Flex items alignment options." | ||
examplePath="components/Flex/Types/FlexExampleItemsAlignment" | ||
/> | ||
<ComponentExample | ||
title="Mixed Alignment" | ||
description="Flex mixed alignment feature." | ||
examplePath="components/Flex/Types/FlexExampleMixedAlignment" | ||
/> | ||
<ComponentExample | ||
title="Columns (item size)" | ||
description="Flex columns example." | ||
examplePath="components/Flex/Types/FlexExampleColumns" | ||
/> | ||
</ExampleSection> | ||
) | ||
|
||
export default Types |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import * as React from 'react' | ||
import Types from './Types' | ||
|
||
const FlexExamples = () => ( | ||
<> | ||
<Types /> | ||
</> | ||
) | ||
|
||
export default FlexExamples |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import * as PropTypes from 'prop-types' | ||
import * as React from 'react' | ||
import * as _ from 'lodash' | ||
import cx from 'classnames' | ||
|
||
import { UIComponent, commonPropTypes } from '../../lib' | ||
import { ReactProps } from '../../types' | ||
import FlexItem from './FlexItem' | ||
import FlexGap from './FlexGap' | ||
|
||
export interface FlexProps { | ||
/** Defines if container should be inline element. */ | ||
inline?: boolean | ||
|
||
/** Sets vertical flow direction. */ | ||
column?: boolean | ||
|
||
/** Allows overflow items to wrap on the next container's line. */ | ||
wrap?: boolean | ||
|
||
/** Controls items alignment in horizontal direction. */ | ||
hAlign?: 'start' | 'center' | 'end' | 'stretch' | ||
kuzhelov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** Controls items alignment in vertical direction. */ | ||
vAlign?: 'start' | 'center' | 'end' | 'stretch' | ||
kuzhelov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** Defines strategy for distributing remaining space between items. */ | ||
space?: 'around' | 'between' | 'evenly' | ||
kuzhelov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** Defines gap between each two adjacent child items. */ | ||
gap?: 'gap.small' | 'gap.medium' | 'gap.large' | ||
|
||
/** Defines container's padding. */ | ||
padding?: 'padding.medium' | ||
|
||
/** Enables debug mode. */ | ||
debug?: boolean | ||
|
||
/** Orders container to fill all parent's space available. */ | ||
fill?: boolean | ||
} | ||
|
||
/** | ||
* Arrange group of items aligned towards common direction. | ||
*/ | ||
class Flex extends UIComponent<ReactProps<FlexProps>> { | ||
static Item = FlexItem | ||
|
||
static Gap = FlexGap | ||
|
||
static displayName = 'Flex' | ||
static className = 'ui-flex' | ||
|
||
static defaultProps = { | ||
as: 'div', | ||
} | ||
|
||
public static propTypes = { | ||
...commonPropTypes.createCommon({ | ||
content: false, | ||
}), | ||
|
||
inline: PropTypes.bool, | ||
|
||
column: PropTypes.bool, | ||
|
||
wrap: PropTypes.bool, | ||
|
||
hAlign: PropTypes.oneOf(['start', 'center', 'end', 'stretch']), | ||
vAlign: PropTypes.oneOf(['start', 'center', 'end', 'stretch']), | ||
|
||
space: PropTypes.oneOf(['around', 'between', 'evenly']), | ||
|
||
gap: PropTypes.oneOf(['gap.small', 'gap.medium', 'gap.large']), | ||
|
||
padding: PropTypes.oneOf(['padding.medium']), | ||
fill: PropTypes.bool, | ||
|
||
debug: PropTypes.bool, | ||
} | ||
|
||
renderComponent({ ElementType, classes, unhandledProps }): React.ReactNode { | ||
return ( | ||
<ElementType className={classes.root} {...unhandledProps}> | ||
{this.renderChildren(classes.gap)} | ||
</ElementType> | ||
) | ||
} | ||
|
||
renderChildren = (gapClasses: string) => { | ||
const { column, gap, children } = this.props | ||
|
||
return React.Children.map(children, (child: React.ReactElement<any>, index) => { | ||
const childElement = | ||
child.type && ((child.type as any) as typeof FlexItem).__isFlexItem | ||
kuzhelov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
? React.cloneElement(child, { | ||
flexDirection: column ? 'column' : 'row', | ||
}) | ||
: child | ||
|
||
const renderGap = index !== 0 | ||
return ( | ||
<> | ||
{renderGap && gap && <Flex.Gap className={cx(`${Flex.className}__gap`, gapClasses)} />} | ||
kuzhelov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{childElement} | ||
</> | ||
) | ||
}) | ||
} | ||
} | ||
|
||
export default Flex |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import * as React from 'react' | ||
|
||
const FlexGap: React.FC<any> = ({ className }) => <div className={className} /> | ||
FlexGap.displayName = 'FlexGap' | ||
kuzhelov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export default FlexGap |
Uh oh!
There was an error while loading. Please reload this page.