Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### Features
- Add `Loader` component @layershifter ([#685](https://github.com/stardust-ui/react/pull/685))

<!--------------------------------[ v0.16.1 ]------------------------------- -->
## [v0.16.1](https://github.com/stardust-ui/react/tree/v0.16.1) (2019-01-10)
[Compare changes](https://github.com/stardust-ui/react/compare/v0.16.0...v0.16.1)
Expand Down
6 changes: 6 additions & 0 deletions docs/src/examples/components/Loader/Types/LoaderExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Loader } from '@stardust-ui/react'
import * as React from 'react'

const LoaderExample: React.FC = () => <Loader />

export default LoaderExample
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Loader } from '@stardust-ui/react'
import * as React from 'react'

const LoaderExampleLabel: React.FC = () => <Loader label="Loading..." />

export default LoaderExampleLabel
21 changes: 21 additions & 0 deletions docs/src/examples/components/Loader/Types/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from 'react'

import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'

const LoaderTypesExamples = () => (
<ExampleSection title="Types">
<ComponentExample
title="Loader"
description="A basic loader."
examplePath="components/Loader/Types/LoaderExample"
/>
<ComponentExample
title="Label"
description="A loader can contain a label."
examplePath="components/Loader/Types/LoaderExampleLabel"
/>
</ExampleSection>
)

export default LoaderTypesExamples
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Loader } from '@stardust-ui/react'
import * as React from 'react'

const LoaderExampleInline: React.FC = () => <Loader inline />

export default LoaderExampleInline
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Grid, Loader } from '@stardust-ui/react'
import * as React from 'react'

const LoaderExampleLabel: React.FC = () => (
<Grid columns={2} variables={{ gridGap: '20px' }}>
<Loader label="At start" labelPosition="start" />
<Loader label="At end" labelPosition="end" />

<Loader label="At above" labelPosition="above" />
<Loader label="At below" labelPosition="below" />
</Grid>
)

export default LoaderExampleLabel
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Grid, Loader } from '@stardust-ui/react'
import * as React from 'react'

const LoaderExampleSize: React.FC = () => (
<Grid columns="3" variables={{ gridGap: '20px' }}>
<Loader size="smallest" />
<Loader size="smaller" />
<Loader size="small" />

<Loader size="large" />
<Loader size="larger" />
<Loader size="largest" />
</Grid>
)

export default LoaderExampleSize
26 changes: 26 additions & 0 deletions docs/src/examples/components/Loader/Variations/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react'

import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'

const LoaderTypesExamples = () => (
<ExampleSection title="Types">
<ComponentExample
title="Inline"
description="Loaders can appear inline with content."
examplePath="components/Loader/Variations/LoaderExampleInline"
/>
<ComponentExample
title="Label Position"
description="A label in the loader can have different positions."
examplePath="components/Loader/Variations/LoaderExampleLabelPosition"
/>
<ComponentExample
title="Size"
description="A size of the loader."
examplePath="components/Loader/Variations/LoaderExampleSize"
/>
</ExampleSection>
)

export default LoaderTypesExamples
13 changes: 13 additions & 0 deletions docs/src/examples/components/Loader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as React from 'react'

import Types from './Types'
import Variations from './Variations'

const LoaderExamples = () => (
<>
<Types />
<Variations />
</>
)

export default LoaderExamples
89 changes: 89 additions & 0 deletions src/components/Loader/Loader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import * as PropTypes from 'prop-types'
import * as React from 'react'

import {
UIComponent,
createShorthandFactory,
UIComponentProps,
commonPropTypes,
ColorComponentProps,
customPropTypes,
} from '../../lib'
import { loaderBehavior } from '../../lib/accessibility'
import { Accessibility } from '../../lib/accessibility/types'
import { ReactProps, ShorthandValue } from '../../../types/utils'
import Slot from '../Slot/Slot'

export type LoaderPosition = 'above' | 'below' | 'start' | 'end'
export type LoaderSize =
| 'smallest'
| 'smaller'
| 'small'
| 'medium'
| 'large'
| 'larger'
| 'largest'

export interface LoaderProps extends UIComponentProps, ColorComponentProps {
/**
* Accessibility behavior if overridden by the user.
* @default defaultBehavior
*/
accessibility?: Accessibility

/** A loader can contain an indicator. */
indicator?: ShorthandValue

/** A loader can contain a label. */
label?: ShorthandValue

/** A label in the loader can have different positions. */
labelPosition?: LoaderPosition

/** A size of the loader. */
size?: LoaderSize
}

/**
* A Loader indicates a possible user action.
*/
class Loader extends UIComponent<ReactProps<LoaderProps>> {
static create: Function
static displayName = 'Loader'
static className = 'ui-loader'

static propTypes = {
...commonPropTypes.createCommon({
children: false,
content: false,
color: true,
}),
accessibility: PropTypes.func,
indicator: customPropTypes.itemShorthand,
label: customPropTypes.itemShorthand,
labelPosition: PropTypes.oneOf(['above', 'below', 'start', 'end']),
size: PropTypes.oneOf(['smallest', 'smaller', 'small', 'medium', 'large', 'larger', 'largest']),
}

static defaultProps = {
accessibility: loaderBehavior,
indicator: '',
labelPosition: 'below',
size: 'medium',
}

renderComponent({ ElementType, classes, accessibility, variables, styles, unhandledProps }) {
const { indicator, label } = this.props

return (
<ElementType className={classes.root} {...accessibility.attributes.root} {...unhandledProps}>
{Slot.create(indicator, { defaultProps: { styles: styles.indicator } })}
{Slot.create(label, { defaultProps: { styles: styles.label } })}
</ElementType>
)
}
}

Loader.create = createShorthandFactory(Loader, 'content')

export default Loader
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export {
} from './components/ItemLayout/ItemLayout'

export { default as Label, LabelProps } from './components/Label/Label'
export { default as Loader, LoaderProps } from './components/Loader/Loader'

export { default as Layout, LayoutPropsWithDefaults, LayoutProps } from './components/Layout/Layout'

Expand Down
19 changes: 19 additions & 0 deletions src/lib/accessibility/Behaviors/Loader/loaderBehavior.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Accessibility } from '../../types'

/**
* @description
* Loader is usually an element that displays the progress status for a task that take a long time or consists of several steps.
*
* @specification
* Adds role 'progressbar' to 'root' component's part.
*/

const loaderBehavior: Accessibility = () => ({
attributes: {
root: {
role: 'progressbar',
},
},
})

export default loaderBehavior
1 change: 1 addition & 0 deletions src/lib/accessibility/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { default as listBehavior } from './Behaviors/List/listBehavior'
export { default as listItemBehavior } from './Behaviors/List/listItemBehavior'
export { default as selectableListBehavior } from './Behaviors/List/selectableListBehavior'
export { default as selectableListItemBehavior } from './Behaviors/List/selectableListItemBehavior'
export { default as loaderBehavior } from './Behaviors/Loader/loaderBehavior'
export { default as inputBehavior } from './Behaviors/Input/inputBehavior'
export { default as iconBehavior } from './Behaviors/Icon/iconBehavior'
export { default as tabBehavior } from './Behaviors/Tab/tabBehavior'
Expand Down
1 change: 1 addition & 0 deletions src/themes/base/componentStyles.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as Loader } from './components/Loader/loaderStyles'
export { default as Text } from './components/Text/textStyles'
1 change: 1 addition & 0 deletions src/themes/base/componentVariables.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as Loader } from './components/Loader/loaderVariables'
export { default as Text } from './components/Text/textVariables'
64 changes: 64 additions & 0 deletions src/themes/base/components/Loader/loaderStyles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { FlexDirectionProperty } from 'csstype'

import { pxToRem } from '../../../../lib'
import { LoaderProps } from '../../../../components/Loader/Loader'
import { ComponentStyleFunctionParam, ICSSInJSStyle } from '../../../types'
import { ObjectOf } from '../../../../../types/utils'
import { LoaderVariables } from './loaderVariables'

const rootFlexDirections: ObjectOf<FlexDirectionProperty> = {
above: 'column-reverse',
below: 'column',
start: 'row-reverse',
end: 'row',
}

export default {
root: ({
props: p,
}: ComponentStyleFunctionParam<LoaderProps, LoaderVariables>): ICSSInJSStyle => ({
alignItems: 'center',
display: p.inline ? 'inline-flex' : 'flex',
justifyContent: 'center',
flexDirection: rootFlexDirections[p.labelPosition],
}),
indicator: ({
props: p,
theme: t,
variables: v,
}: ComponentStyleFunctionParam<LoaderProps, LoaderVariables>): ICSSInJSStyle => {
const animationName = t.renderer.renderKeyframe(
() =>
({
from: {
transform: 'rotate(0deg)',
},
to: {
transform: 'rotate(360deg)',
},
} as any),
{},
)
const borderColor = `${v.foregroundColor} ${v.backgroundColor} ${v.backgroundColor}`

return {
animationName,
animationDuration: '1.3s',
animationIterationCount: 'infinite',
animationTimingFunction: 'cubic-bezier(0.53, 0.21, 0.29, 0.67)',

borderColor,
borderRadius: '50%',
borderStyle: 'solid',
borderWidth: v.borderSizes[p.size],

boxSizing: 'border-box',

width: v.indicatorSizes[p.size],
height: v.indicatorSizes[p.size],
}
},
label: {
margin: pxToRem(10),
},
}
38 changes: 38 additions & 0 deletions src/themes/base/components/Loader/loaderVariables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { pxToRem } from '../../../../lib'
import { LoaderSize } from '../../../../components/Loader/Loader'

export interface LoaderVariables {
foregroundColor: string
backgroundColor: string

borderSizes: Record<LoaderSize, string>
indicatorSizes: Record<LoaderSize, string>
}

export default (siteVariables): LoaderVariables => ({
foregroundColor: siteVariables.colors.grey[400],
backgroundColor: siteVariables.colors.grey[100],

borderSizes: {
smallest: pxToRem(1.5),
small: pxToRem(2),
smaller: pxToRem(2),

medium: pxToRem(2),

large: pxToRem(2.5),
larger: pxToRem(3),
largest: pxToRem(4),
},
indicatorSizes: {
smallest: pxToRem(16),
small: pxToRem(20),
smaller: pxToRem(22),

medium: pxToRem(24),

large: pxToRem(26),
larger: pxToRem(30),
largest: pxToRem(34),
},
})
2 changes: 2 additions & 0 deletions test/specs/behaviors/behavior-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
iconBehavior,
imageBehavior,
inputBehavior,
loaderBehavior,
menuBehavior,
menuItemBehavior,
submenuBehavior,
Expand Down Expand Up @@ -45,6 +46,7 @@ testHelper.addBehavior('buttonBehavior', buttonBehavior)
testHelper.addBehavior('iconBehavior', iconBehavior)
testHelper.addBehavior('inputBehavior', inputBehavior)
testHelper.addBehavior('imageBehavior', imageBehavior)
testHelper.addBehavior('loaderBehavior', loaderBehavior)
testHelper.addBehavior('menuBehavior', menuBehavior)
testHelper.addBehavior('menuItemBehavior', menuItemBehavior)
testHelper.addBehavior('submenuBehavior', submenuBehavior)
Expand Down
6 changes: 6 additions & 0 deletions test/specs/components/Loader/Loader-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { isConformant } from 'test/specs/commonTests'
import Loader from 'src/components/Loader/Loader'

describe('Loader', () => {
isConformant(Loader)
})