Skip to content
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

fix(List): Update to v1 API #551

Merged
merged 12 commits into from
Oct 1, 2016
Merged

fix(List): Update to v1 API #551

merged 12 commits into from
Oct 1, 2016

Conversation

layershifter
Copy link
Member

@layershifter layershifter commented Sep 26, 2016

This PR updates List component to v1 API.

@levithomason levithomason changed the title fix(Label): Update to v1 API fix(List): Update to v1 API Sep 26, 2016
</List.Content>
</List.Item>
<List.Item>
<List.Icon name='github' size='large' verticalAlign='middle' />
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have there hateful situation, Icon doesn't have prop verticalAlign but .list .icon has. I don't like idea with List.Icon, may be something better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For clarity, we're talking about this:

image

Oh boy :/ The proper extrapolation of our API is to add List.Icon. However, odds of users using this over Icon are slim. Especially considering all other components use the Icon directly.

I think we add verticalAlign to the Icon itself. I realize that prop would only be valid when used in a List, but it seems to make the most sense for users.

Any other wise ideas @jcarbo?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think List.Icon might actually be the way to go. It would just be a wrapper around Icon that handles the verticalAlign prop:

function ListIcon(props) {
  const { verticalAlign, className } = props
  const classes = cx(
    useValueAndKey(verticalAlign, 'verticalAlign'),
    className
  )
  const rest = getUnhandledProps(ListIcon, props)
  return <Icon {...rest} className={classes} />
}

In all likelihood, if I were using a List I'd either be:

  • using the icon prop as a shorthand, so it wouldn't matter whether it's Icon or List.Icon under the hood.
  • looking at the example page for List to see how to structure it and would see the List.Icon subcomponent there.

I could also see just building it into the Icon class with a comment noting that it's a specific use-case, although I really wish there were at least one other use-case for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I was on the fence as well, but after sleeping on it and hearing this I think we should stick with the API pattern we've chosen rather than make an exception.

@layershifter let's keep it consistent and go with List.Icon. Thanks for the input guys.

@codecov-io
Copy link

codecov-io commented Sep 26, 2016

Current coverage is 99.61% (diff: 100%)

Merging #551 into master will increase coverage by 0.12%

@@             master       #551   diff @@
==========================================
  Files           112        117     +5   
  Lines          1767       1807    +40   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits           1758       1800    +42   
+ Misses            9          7     -2   
  Partials          0          0          

Powered by Codecov. Last update a89545d...ff77fc0

const rest = getUnhandledProps(ListItem, props)
const valueProp = ElementType === 'li' ? { value } : { dataValue: value }

return <ElementType {...rest} {...valueProp} className={classes}>{children}</ElementType>
Copy link
Member Author

@layershifter layershifter Sep 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comrades, what you think about this (valueProp)? May be more elegant solution possible there?

I'm talking about this:

<li value="*">User Benefits</li>

You can also manually specify a value for an ordered list using data-value on a div, or value on an li

Copy link
Member

@levithomason levithomason Sep 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any React warnings when adding value to an <li>. Any reason not to with this?

<List.Item value='*' />
//=> <li value="*"></li>

If there is an issue, one alternative could be to use bullet:

<List.Item bullet='#' />
//=> <li value="#"></li>

Though, I'd lean toward SUI parity if we can.

Copy link
Member Author

@layershifter layershifter Sep 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm talking about this transform, it looks not very clean (valueProp spreading).

<List.Item value='*' />
//=> <div data-value="*"></div>

<List.Item as='li' value='*' />
//=> <li value="*"></li>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I believe the conditional you have now is acceptable. It is the same approach I would take as a first try.

const ElementType = getElementType(ListList, props)
const classes = cx(
className,
useKeyOnly(ElementType !== 'ul' && ElementType !== 'ol', 'list'),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another evil place with class handling, see SUI docs about ul & ol.
Combo like Menu.Menu is there, too :-\

<List>
  <List.Item>
    Item
    <List.List>
      <List.Item>Sub item</List.Item>
    </List.List>
  </List.Item>
</List>
// ...
// <div class="ui list">
//   <div class="item">
//     <div class="list">...</div>
//   </div>
// </div>
// ...
<List as='ul'>
  <List.Item as='li'>
    Item
    <List.List as='ul'>
      <List.Item as='li'>Sub item</List.Item>
    </List.List>
  </List.Item>
</List>
// ...
// <ul class="ui list">
//   <li>
//     <ul>...</ul>
//   </li>
// </ul>
// ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the docs the "list" class may be omitted "as a convenience" when using an "ol" or "ul" tag. Though, I don't think it is required to be omitted. We can likely always have the "list" class present.

I suspect we can also have the "item" class on all items as well. Let's try always having the classes first. That way, the components are more simple.

Copy link
Member Author

@layershifter layershifter Sep 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the docs the "list" class may be omitted "as a convenience" when using an "ol" or "ul" tag.

Sad, but it must be omitted.

Without classes:
image
With classes:
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh boy, well then. I think the logic you originally had there is just the way it has to be.

@layershifter
Copy link
Member Author

Ahoy, docs are fully there 🚢

Working on tests.

@levithomason
Copy link
Member

Awesome, pulling and trying them out. Will let you know.

Copy link
Member

@levithomason levithomason left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once again, thanks for the massive amount of work here. Especially for keeping up to date on all the latest decisions and incorporating them here. It is very much appreciated!

I've left a few comments. I'll update common tests as well, then we should update this branch to have the latest.

</ElementType>
)
}
function List(props) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add the component description from the SUI docs as well.

/>
<ComponentExample examplePath='elements/List/Types/ListExampleBulletedSimple'>
<Message info>
For convenience, a simple bulleted list can also use <code>ul</code> tag.
Copy link
Member

@levithomason levithomason Sep 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this message is only applicable to SUI core where the user defines HTML/CSS. Since, in Semantic-UI-React the classNames are hidden from the user. Let's go ahead and remove this.

/>
<ComponentExample examplePath='elements/List/Types/ListExampleOrderedSimple'>
<Message info>
You can also manually specify a value for an ordered list using <code>value</code>.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message belongs on the next example.

import React from 'react'
import { Image, List } from 'stardust'

const ListExampleHorizontalNumbered = () => (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about we rename this ListExampleHorizontalOrdered to keep with the prop name?

name: 'List',
type: META.TYPES.ELEMENT,
props: {
floated: ['left', 'right'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use SUI.FLOATS here for the values.

parent: 'List',
type: META.TYPES.ELEMENT,
props: {
floated: ['left', 'right'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use SUI.FLOATS here for the values.

useKeyOnly(active, 'active'),
useKeyOnly(disabled, 'disabled'),
className,
useKeyOnly(ElementType !== 'li', 'item'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this up so the user's className is added very last?

@@ -24,6 +24,8 @@ export { default as Input } from './Input/Input'
export { default as Label } from './Label/Label'
export { default as LabelDetail } from './Label/LabelDetail'

// TODO: Export `List`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is done now, but we should export the rest of the List sub components as well. I'll add a common test that ensures all components are exported at the top level as well.

@layershifter
Copy link
Member Author

I've fixed comments and added tests.

There is one failed test on Icon, could you please fix it? I have to move away for a few hours 😢
After fixes, we're ready to go as I think 👍

@layershifter
Copy link
Member Author

Updated to latest master and fixed test. @levithomason your move 👍

@levithomason
Copy link
Member

I'll release this later today, thanks much!

@levithomason levithomason deleted the feat/list branch October 1, 2016 23:24
@levithomason
Copy link
Member

Released in stardust@0.49.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants