-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Step component #335
Add Step component #335
Conversation
…into feature/rail
…into feature/step
Current coverage is 93.76% (diff: 100%)@@ master #335 diff @@
==========================================
Files 68 73 +5
Lines 898 946 +48
Methods 0 0
Messages 0 0
Branches 0 0
==========================================
+ Hits 839 887 +48
Misses 59 59
Partials 0 0
|
if (!icon) return <div className='content'>{getChildren()}</div> | ||
|
||
return [iconPropRenderer(icon), <div className='content'>{getChildren()}</div>].map((item) => item) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@levithomason may be cleaner solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored this fragment, it might be more understantable now 👍 |
I see, it looks like we're abstracting away the There are many components that have Because of the need to sometimes configure content, and given our sub component API pattern, we may likely end up supporting Content parts something like this: <Card>
<Card.Content>...</Card.Content>
<Card.Content extra>...</Card.Content>
</Card>
<Modal>
<Modal.Content>...</Modal.Content>
<Modal.Content image>...</Modal.Content>
</Modal>
<Item>
<Item.Content>...</Item.Content>
<Item.Content aligned='bottom'>...</Item.Content>
</Item> This would mean for the Step: <Step>
<Step.Content>...</Step.Content>
</Step> Again, I'm open for ideas and input here but this is where I'm leaning so far. EDIT To be clear,
|
@levithomason Seems it make code cleaner, I'll refactor |
Sounds good |
I think it's ready for review :) I've updated |
@levithomason seems there is only one problem to solve, waiting for your opinion |
ping @levithomason |
Taking a look! |
Would you mind rebasing this PR to the latest master? It would help with the review. |
Yes, give me five minutes |
Made 😋 |
Thanks much, looking at Feed right now. Will get to this next. |
I think your fork needs to update it's master to the upstream master. I'm still able to review now however. |
Fixing LinksThere 2 are changes necessary to fix the links example: 1. StepLinkExamples.js Spread props on the - return <Step active={this.state.active} onClick={this.handleClick} />
+ return <Step {...this.props} active={this.state.active} onClick={this.handleClick} /> 2. StepGroup.js Because -if (items) {
- return (
- <div {...rest} className={classes}>
- {items.map((item, index) => <Step key={index} {...item} ordered={ordered} />)}
- </div>
- )
-}
-
-return (
- <div {...rest} className={classes}>
- {mapChildType(children, Step, (step, index) => (
- <Step {...step.props} key={index} ordered={ordered} />
- ))}
- </div>
-)
+const content = items
+ ? items.map((item, index) => <Step key={index} {...item} ordered={ordered} />)
+ : children
+
+return <div {...rest} className={classes}>{content}</div> Ordered UpdatesSince we no longer map Steps in the Group and add the ordered prop, we need to handle this now. The Step looks like it was only using Step.js const {
- active, className, children, completed, description, disabled, icon, href, link, onClick, ordered, title,
+ active, className, children, completed, description, disabled, icon, href, link, onClick, title,
} = props
-const contentJSX = completed || icon || ordered ? [
- icon && iconPropRenderer(icon, { key: icon }),
- children && <StepContent key='content' children={children} />,
- (title || description) && <StepContent key='content' description={description} title={title} />,
-] : [
- children && children,
- title && <StepTitle key='title' title={title} />,
- description && <StepDescription key='description' description={description} />,
-]
const StepComponent = href || onClick ? 'a' : 'div'
return (
<StepComponent
{...rest}
className={classes}
href={href}
onClick={handleClick}
>
- {contentJSX}
+ {!children && iconPropRenderer(icon)}
+ {children || <StepContent description={description} title={title} />}
</StepComponent>
) For consistency, simplicity, and due to other component conflicts, the /** A step can contain an icon. */
- icon: PropTypes.string,
+ icon: customPropTypes.all([
+ customPropTypes.mutuallyExclusive(['children']),
+ PropTypes.node,
+ ]), We could technically allow Update ExamplesWith the above changes, we'll need to use either the props API or subcomponent API, but not both simultaneously. We also need to include the StepGroupExample.js -import { Step } from 'stardust'
+ import { Icon, Step } from 'stardust'
-<Step icon='truck'>
+<Step>
+ <Icon name='truck' />
+ <Step.Content>
<Step.Title>Shipping</Step.Title>
<Step.Description>Choose your shipping options</Step.Description>
+ </Step.Content>
</Step> With all these changes, everything seems to work in the docs and components. It also seems more simple, which is good. LMK how the updates go! |
Thanks for review. Fixing Links1. StepLinkExamples.jsAgree, it works. 2. StepGroup.jsitems.map((item, index) => <Step key={index} {...item} ordered={ordered} />) Antipattern with const {description, title} = item
const key = `${title}-${description}` Ordered UpdatesI don't like these updates because they will break this nice layout: <Step icon='truck'>
<Title>Shipping</Title>
<Description>Choose your shipping options</Description>
</Step> May be we can use React.Content for passing |
That is much better. We can allow them to pass a key in the items array. How about something like this (accounts for undefined title/description): items.map((item) => {
const key = item.key || [item.title, item.description].join('-')
return <Step key={key} {...item} />
})
TL;DR at the bottom 😄 The markup Step > Title, Description is definitely cleaner than Step > Content > Title, Description. However, consider other components with <h2 class="ui header">Account Settings</h2>
<h2 class="ui icon header">
<i class="settings icon"></i>
<div class="content">
Account Settings
</div>
</h2> <div class="ui card">
<div class="image">
<img src="/images/avatar2/large/kristy.png">
</div>
<div class="content">...</div>
</div> <div class="ui comments">
<div class="comment">
<a class="avatar">
<img src="/images/avatar/small/joe.jpg">
</a>
<div class="content">... </div>
</div>
</div> At first, it seems safe to abstract away the I see three places this could break down and cause issues. First, if a user needed to pass something more complicated than a basic icon name or image src through the props then it could get ugly and painful. Second, I think it would be an issue if only some of our components allowed use of I think all of these issues are already present. At TA we had a fair number of use cases where we had to pass complicated components through shorthand props that fully abstracted away access to parts of the render tree. It made for very ugly code and markup issues that would not be present if we had full access and control to the component markup. We also have components in the library with const header = (
// extra node to wrap text :( sometimes breaks styles
<span>
Here is my header
<Icon style={closeIconStyle} name='close icon' onClick={this.hideModal} />
</span>
)
<Modal header={header}>...</Modal>
<div class="ui modal">
<div class="header">
<span>
Here is my header
<Icon name='close icon' />
</span>
</div>
<div class="content">...</div>
</div> Whereas, if we did not abstract away access to the <Modal>
<Modal.Header>
This is my header
<Icon style={closeIconStyle} name='close icon' onClick={this.hideModal} />
</Modal.Header>
<Modal.Content>
...
</Modal.Content>
</Modal>
<div class="ui modal">
<div class="header">
Here is my header
<Icon name='close icon' />
</div>
<div class="content">...</div>
</div> There are also components which take props on the content. Like vertically aligned lists, modals with image content, animated buttons, and probably others. These could be hoisted up to the top level, but this again is making the assumption that there will never be conflicting props between the top component and the content. TL;DRIn conclusion, completely abstracting away Because of this, I think our first version should offer the props API for simple use cases, offer the subcomponent API for use cases beyond the smiple, and make these two mutually exclusive. P.S. Personally, I like mixing the props API and sub component APIs to abstract away |
@levithomason thanks for a detailed point of view 👍 |
No problem, explaining helps me to better understand it myself! |
Once the step/examples are updated, I think we can merge this one |
I've updated all, so let's go 🚗 |
Woop! I'll make some doc updates soon. Need to remove |
* (feat) Rail #181 * (feat) Rail #181 * (feat) Rail docs #181 * (fix) Sort Rail props #181 * (fix) Rail review fixes #181 * (fix) Rail review fixes #181 * (fix) Rail review fixes #181 * (fix) Rail sizes #181 * (fix) Rail sizes in docs #181 * (feat) Step Title * feat(Step) Step component * feat(Step) Step component * feat(Step) Step component * feat(Step) Examples and implements * feat(Step) Fix * fix(Step) Refactor fragment * feat(Step) Shorthand props * feat(Step) More docs and feats * feat(Parts) Title & Description * feat(Parts) Move code to parts * feat(Parts) Step cleanup * fix(Step) Fix doc and prop * fix(Step) Fix for content * fix(Step) Fix examples and components * fix(Step) Fix comment * fix(Step) Fix prop and tests * fix(Step) Content test * feat(Step) Tests for group * feat(Step) Tests for Step * fix(Step) Add test for children * fix(Step) Update example * fix(Step) Remove library from _meta * fix(Step) Fix link example * fix(Step) Update components, docs and tests
API
Types
Step
A single step
Groups
Steps
A set of steps
Ordered
A step can show a ordered sequence of steps
Vertical
A step can be displayed stacked vertically
Content
Description
A step can contain a description
Already described
Icon
A step can contain an icon
Already described
Link
A step can link
States
Active
A step can be highlighted as active
Already described
Completed
A step can show that a user has completed it
Already described
Disabled
A step can show that it cannot be selected
Variations
Stackable
A step can stack vertically only on smaller screens
Vertical
A step can be displayed stacked vertically
Fluid
A fluid step takes up the width of its container
Attached
Steps can be attached to other elements
Evenly Divided
Steps can be divided evenly inside their parent
Equal Width
Explicit Widths
Size
Steps can have different sizes
Fixes #183