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

refactor(Rating): add rating icon component #640

Merged
merged 7 commits into from
Oct 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react'
import { Rating } from 'semantic-ui-react'

const RatingClearableExample = () => (
const RatingExampleClearable = () => (
<Rating maxRating={5} clearable />
)

export default RatingClearableExample
export default RatingExampleClearable
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import { Rating } from 'semantic-ui-react'

export default class RatingControlledExample extends Component {
export default class RatingExampleControlled extends Component {
state = { rating: 0 }

handleChange = (e) => this.setState({ rating: e.target.value })
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react'
import { Rating } from 'semantic-ui-react'

const RatingDisabledExample = () => (
const RatingExampleDisabled = () => (
<Rating defaultRating={3} maxRating={5} disabled />
)

export default RatingDisabledExample
export default RatingExampleDisabled
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react'
import { Rating } from 'semantic-ui-react'

const RatingHeartExample = () => (
const RatingExampleHeart = () => (
<Rating icon='heart' defaultRating={1} maxRating={3} />
)

export default RatingHeartExample
export default RatingExampleHeart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import { Rating } from 'semantic-ui-react'

export default class RatingOnRateExample extends Component {
export default class RatingExampleOnRate extends Component {
state = {}

handleRate = (e, { rating, maxRating }) => this.setState({ rating, maxRating })
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react'
import { Rating } from 'semantic-ui-react'

const RatingExample = () => (
const RatingExampleRating = () => (
<Rating />
)

export default RatingExample
export default RatingExampleRating
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react'
import { Rating } from 'semantic-ui-react'

const RatingStarExample = () => (
const RatingExampleStar = () => (
<Rating icon='star' defaultRating={3} maxRating={4} />
)

export default RatingStarExample
export default RatingExampleStar
46 changes: 46 additions & 0 deletions docs/app/Examples/modules/Rating/Types/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react'

import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'

const RatingTypes = () => (
<ExampleSection title='Types'>
<ComponentExample
title='Rating'
description='A basic rating.'
examplePath='modules/Rating/Types/RatingExampleRating'
/>
<ComponentExample
title='Star'
description='A rating can use a set of star icons.'
examplePath='modules/Rating/Types/RatingExampleStar'
/>
<ComponentExample
title='Heart'
description='A rating can use a set of heart icons.'
examplePath='modules/Rating/Types/RatingExampleHeart'
/>
<ComponentExample
title='Clearable'
description='A rating can be cleared by clicking again.'
examplePath='modules/Rating/Types/RatingExampleClearable'
/>
<ComponentExample
title='Disabled'
description='A rating can be disabled.'
examplePath='modules/Rating/Types/RatingExampleDisabled'
/>
<ComponentExample
title='Controlled'
description='A rating can be a controlled component.'
examplePath='modules/Rating/Types/RatingExampleControlled'
/>
<ComponentExample
title='onRate Callback'
description='A rating calls back when the rating changes.'
examplePath='modules/Rating/Types/RatingExampleOnRate'
/>
</ExampleSection>
)

export default RatingTypes
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import { Rating } from 'semantic-ui-react'

const RatingSizeExample = () => (
const RatingExampleSize = () => (
<div>
<Rating maxRating={5} defaultRating={3} icon='star' size='mini' />
<br />
Expand Down Expand Up @@ -32,4 +32,4 @@ const RatingSizeExample = () => (
<br />
</div>
)
export default RatingSizeExample
export default RatingExampleSize
16 changes: 16 additions & 0 deletions docs/app/Examples/modules/Rating/Variations/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react'

import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'

const RatingVariations = () => (
<ExampleSection title='Variations'>
<ComponentExample
title='Size'
description='A rating can vary in size.'
examplePath='modules/Rating/Variations/RatingExampleSize'
/>
</ExampleSection>
)

export default RatingVariations
66 changes: 11 additions & 55 deletions docs/app/Examples/modules/Rating/index.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,13 @@
import React, { Component } from 'react'
import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'
import React from 'react'

export default class RatingExamples extends Component {
render() {
return (
<div>
<ExampleSection title='Types'>
<ComponentExample
title='Rating'
description='A basic rating'
examplePath='modules/Rating/Types/RatingRatingExample'
/>
<ComponentExample
title='Star'
description='A rating can use a set of star icons'
examplePath='modules/Rating/Types/RatingStarExample'
/>
<ComponentExample
title='Heart'
description='A rating can use a set of heart icons'
examplePath='modules/Rating/Types/RatingHeartExample'
/>
<ComponentExample
title='Clearable'
description='A rating can be cleared by clicking again'
examplePath='modules/Rating/Types/RatingClearableExample'
/>
<ComponentExample
title='Disabled'
description='A rating can be disabled'
examplePath='modules/Rating/Types/RatingDisabledExample'
/>
<ComponentExample
title='Controlled'
description='A rating can be a controlled component'
examplePath='modules/Rating/Types/RatingControlledExample'
/>
<ComponentExample
title='onRate Callback'
description='A rating calls back when the rating changes'
examplePath='modules/Rating/Types/RatingOnRateExample'
/>
</ExampleSection>
import Types from './Types'
import Variations from './Variations'

<ExampleSection title='Variations'>
<ComponentExample
title='Size'
description='A rating can vary in size'
examplePath='modules/Rating/Variations/RatingSizeExample'
/>
</ExampleSection>
</div>
)
}
}
const RatingExamples = () => (
<div>
<Types />
<Variations />
</div>
)

export default RatingExamples
68 changes: 31 additions & 37 deletions src/modules/Rating/Rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import {
getUnhandledProps,
META,
SUI,
useKeyOnly,
} from '../../lib'
import RatingIcon from './RatingIcon'

const _meta = {
name: 'Rating',
Expand All @@ -21,6 +23,9 @@ const _meta = {
},
}

/**
* A rating indicates user interest in content
*/
export default class Rating extends Component {
static autoControlledProps = [
'rating',
Expand Down Expand Up @@ -48,6 +53,15 @@ export default class Rating extends Component {
PropTypes.bool,
]),

/** The initial rating value. */
defaultRating: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),

/** You can disable or enable interactive rating. Makes a read-only rating. */
disabled: PropTypes.bool,

/** A rating can use a set of star or heart icons. */
icon: PropTypes.oneOf(_meta.props.icon),

Expand All @@ -57,26 +71,17 @@ export default class Rating extends Component {
PropTypes.number,
]),

/** Called with (event, { rating, maxRating }) after user selects a new rating. */
onRate: PropTypes.func,

/** The current number of active icons. */
rating: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),

/** The initial rating value. */
defaultRating: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),

/** A progress bar can vary in size. */
size: PropTypes.oneOf(_meta.props.size),

/** You can disable or enable interactive rating. Makes a read-only rating. */
disabled: PropTypes.bool,

/** Called with (event, { rating, maxRating }) after user selects a new rating. */
onRate: PropTypes.func,
}

static _meta = _meta
Expand Down Expand Up @@ -115,42 +120,22 @@ export default class Rating extends Component {
this.setState({ selectedIndex: -1, isSelecting: false })
}

renderIcons = () => {
const { maxRating } = this.props
const { rating, selectedIndex, isSelecting } = this.state

return _.times(maxRating, (i) => {
const classes = cx(
selectedIndex >= i && isSelecting && 'selected',
rating >= i + 1 && 'active',
'icon'
)
return (
<i
key={i}
className={classes}
onClick={(e) => this.handleIconClick(e, i)}
onMouseEnter={() => this.handleIconMouseEnter(i)}
/>
)
})
}

render() {
const {
className,
disabled,
icon,
maxRating,
size,
} = this.props
const { selectedIndex, isSelecting } = this.state
const { rating, selectedIndex, isSelecting } = this.state

const classes = cx(
'ui',
disabled && 'disabled',
icon,
isSelecting && !disabled && selectedIndex >= 0 && 'selected',
size,
useKeyOnly(disabled, 'disabled'),
useKeyOnly(isSelecting && !disabled && selectedIndex >= 0, 'selected'),
'rating',
className,
)
Expand All @@ -159,7 +144,16 @@ export default class Rating extends Component {

return (
<ElementType {...rest} className={classes} onMouseLeave={this.handleMouseLeave}>
{this.renderIcons()}
{_.times(maxRating, (i) => (
<RatingIcon
active={rating >= i + 1}
index={i}
key={i}
onClick={this.handleIconClick}
onMouseEnter={this.handleIconMouseEnter}
selected={selectedIndex >= i && isSelecting }
/>
))}
</ElementType>
)
}
Expand Down
Loading