Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

feat(Dropdown): add loading prop #729

Merged
merged 25 commits into from
Jan 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6d08667
feat(Dropdown): add `loading` prop
layershifter Jan 15, 2019
00d8b83
push cleanups
layershifter Jan 17, 2019
de8fcc1
add changelog entry
layershifter Jan 17, 2019
d2564b3
add prototype
layershifter Jan 17, 2019
36d2eef
revert some changes
layershifter Jan 22, 2019
19e5d45
fix export names
layershifter Jan 22, 2019
056f81e
Merge branches 'feat/dropdown-loading' and 'master' of https://github…
layershifter Jan 22, 2019
8b61a89
more cleanups
layershifter Jan 22, 2019
ec5bb2a
more cleanups
layershifter Jan 22, 2019
8fe5741
final cleanups
layershifter Jan 22, 2019
e908485
Merge branch 'master' of https://github.com/stardust-ui/react into fe…
layershifter Jan 22, 2019
1b4772e
update description
layershifter Jan 22, 2019
ec11785
rename to `toggleIndicatorSize`
layershifter Jan 22, 2019
0e3c61c
fix JSON mode
layershifter Jan 22, 2019
d88dbce
reduce items in example
layershifter Jan 22, 2019
e9cb73a
Merge branch 'master' of https://github.com/stardust-ui/react into fe…
layershifter Jan 22, 2019
514c023
wip
layershifter Jan 23, 2019
313d4ff
remove useless components
layershifter Jan 23, 2019
0cdd20e
revert some changes
layershifter Jan 23, 2019
b00faa9
update comment
layershifter Jan 23, 2019
d14cef7
fix keys
layershifter Jan 23, 2019
4d00a20
fix broken UT
layershifter Jan 23, 2019
d30c9f9
remove selector
layershifter Jan 23, 2019
3a97807
Merge branches 'feat/dropdown-loading' and 'master' of https://github…
layershifter Jan 24, 2019
c14e633
Merge branches 'feat/dropdown-loading' and 'master' of https://github…
layershifter Jan 24, 2019
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### BREAKING CHANGES
- Update variable names in themes, add missing sizes @layershifter ([#762](https://github.com/stardust-ui/react/pull/762))
- Rename `toggleButton` prop to `toggleIndicator` and make it visible by default @layershifter ([#729](https://github.com/stardust-ui/react/pull/729))

### Features
- Add `loading` prop for `Dropdown` @layershifter ([#729](https://github.com/stardust-ui/react/pull/729))

<!--------------------------------[ v0.18.0 ]------------------------------- -->
## [v0.18.0](https://github.com/stardust-ui/react/tree/v0.18.0) (2019-01-24)
Expand Down
22 changes: 16 additions & 6 deletions docs/src/components/CodeSnippet.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
import * as _ from 'lodash'
import * as React from 'react'

import formatCode from '../utils/formatCode'
import Editor, { EDITOR_BACKGROUND_COLOR } from './Editor'

export type CodeSnippetValue = string | string[] | Object

export interface CodeSnippetProps {
fitted?: boolean
label?: string
mode?: 'jsx' | 'html' | 'sh'
value: string | string[]
mode?: 'json' | 'jsx' | 'html' | 'sh'
value: CodeSnippetValue
style?: React.CSSProperties
}

const joinToString = (stringOrArray: string | string[]) => {
return typeof stringOrArray === 'string' ? stringOrArray : stringOrArray.join('\n')
const normalizeToString = (value: CodeSnippetValue): string => {
if (_.isArray(value)) return value.join('\n')
return _.isObject(value) ? JSON.stringify(value, null, 2) : (value as string)
}

const formatters = {
sh: (val: string = ''): string => val.replace(/^/g, '$ '),
html: (val: string = ''): string => formatCode(val, 'html'),
json: (val: string): string => val,
jsx: (val: string = ''): string => formatCode(val, 'babylon'),
}

const CodeSnippet = ({ fitted, label, value, mode = 'jsx', ...restProps }: CodeSnippetProps) => {
const CodeSnippet = ({ fitted, label, mode, value, ...restProps }: CodeSnippetProps) => {
const format = formatters[mode]
const formattedValue = format(joinToString(value))
const formattedValue = format(normalizeToString(value))
// remove eof line break, they are not helpful for snippets
.replace(/\n$/, '')

Expand Down Expand Up @@ -66,4 +71,9 @@ const CodeSnippet = ({ fitted, label, value, mode = 'jsx', ...restProps }: CodeS
</div>
)
}

CodeSnippet.defaultProps = {
mode: 'jsx',
}

export default CodeSnippet
5 changes: 3 additions & 2 deletions docs/src/components/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import AceEditor, { AceEditorProps } from 'react-ace'
import * as ace from 'brace'
import 'brace/ext/language_tools'
import 'brace/mode/html'
import 'brace/mode/json'
import 'brace/mode/jsx'
import 'brace/mode/sh'
import 'brace/theme/tomorrow_night'
Expand Down Expand Up @@ -47,7 +48,7 @@ languageTools.addCompleter(semanticUIReactCompleter)
export interface EditorProps extends AceEditorProps {
active?: boolean
highlightGutterLine?: boolean
mode?: 'html' | 'jsx' | 'sh'
mode?: 'html' | 'jsx' | 'sh' | 'json'
value?: string
showCursor?: boolean
}
Expand All @@ -61,7 +62,7 @@ class Editor extends React.Component<EditorProps> {

static propTypes = {
value: PropTypes.string.isRequired,
mode: PropTypes.oneOf(['html', 'jsx', 'sh']),
mode: PropTypes.oneOf(['html', 'json', 'jsx', 'sh']),
active: PropTypes.bool,
showCursor: PropTypes.bool,
}
Expand Down
8 changes: 8 additions & 0 deletions docs/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,14 @@ class Sidebar extends React.Component<any, any> {
>
Chat message with popover
</Menu.Item>
<Menu.Item
as={NavLink}
exact
to="/prototype-async-dropdown-search"
activeClassName="active"
>
Async Dropdown Search
</Menu.Item>
<Menu.Item
as={NavLink}
exact
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react'
import Knobs from 'docs/src/components/Knobs/Knobs'

type DropdownExampleLoadingKnobsProps = {
loading?: boolean
onKnobChange: () => void
}

const DropdownExampleLoadingKnobs: React.FC<DropdownExampleLoadingKnobsProps> = props => {
const { loading, onKnobChange } = props

return (
<Knobs>
<Knobs.Boolean name="loading" onChange={onKnobChange} value={loading} />
</Knobs>
)
}

DropdownExampleLoadingKnobs.defaultProps = {
loading: true,
}

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

const inputItems = ['Bruce Wayne', 'Natasha Romanoff', 'Steven Strange', 'Alfred Pennyworth']

const DropdownExampleLoading: React.FC<{ knobs: { loading: boolean } }> = ({ knobs }) => (
<Dropdown
loading={knobs.loading}
loadingMessage="Loading..."
multiple
items={inputItems}
placeholder="Start typing a name"
search
/>
)

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

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

const State = () => (
<ExampleSection title="State">
<ComponentExample
title="Loading"
description="A dropdown can show that it is currently loading data."
examplePath="components/Dropdown/State/DropdownExampleLoading"
/>
</ExampleSection>
)

export default State

This file was deleted.

5 changes: 0 additions & 5 deletions docs/src/examples/components/Dropdown/Variations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ const Variations = () => (
description="A multiple search dropdown that fits the width of the container."
examplePath="components/Dropdown/Variations/DropdownExampleMultipleSearchFluid"
/>
<ComponentExample
title="Multiple Search with Toggle Button"
description="A multiple search dropdown with toggle button that shows/hides the items list."
examplePath="components/Dropdown/Variations/DropdownExampleMultipleSearchToggleButton"
/>
</ExampleSection>
)

Expand Down
2 changes: 2 additions & 0 deletions docs/src/examples/components/Dropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import * as React from 'react'

import Types from './Types'
import Variations from './Variations'
import State from './State'
import Usage from './Usage'

const DropdownExamples = () => (
<div>
<Types />
<Variations />
<State />
<Usage />
</div>
)
Expand Down
102 changes: 102 additions & 0 deletions docs/src/prototypes/AsyncDropdownSearch/AsyncDropdownSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { Divider, Dropdown, DropdownProps, Header, Loader, Segment } from '@stardust-ui/react'
import * as faker from 'faker'
import * as _ from 'lodash'
import * as React from 'react'

import CodeSnippet from '../../components/CodeSnippet'

// ----------------------------------------
// Types
// ----------------------------------------
type Entry = {
header: string
image: string
content: string
}

interface SearchPageState {
loading: boolean
items: Entry[]
searchQuery: string
value: Entry[]
}

// ----------------------------------------
// Mock Data
// ----------------------------------------
const createEntry = (): Entry => ({
image: faker.internet.avatar(),
header: `${faker.name.firstName()} ${faker.name.lastName()}`,
content: faker.commerce.department(),
})

// ----------------------------------------
// Prototype Search Page View
// ----------------------------------------
class AsyncDropdownSearch extends React.Component<{}, SearchPageState> {
state = {
loading: false,
searchQuery: '',
items: [],
value: [],
}

searchTimer: number

handleSelectedChange = (e: React.SyntheticEvent, { searchQuery, value }: DropdownProps) => {
this.setState({ value: value as Entry[], searchQuery })
}

handleSearchQueryChange = (e: React.SyntheticEvent, { searchQuery }: DropdownProps) => {
this.setState({ searchQuery })
this.fetchItems()
}

fetchItems = () => {
clearTimeout(this.searchTimer)
this.setState({ loading: true })

this.searchTimer = setTimeout(() => {
this.setState(prevState => ({
loading: false,
items: [...prevState.items, ..._.times<Entry>(10, createEntry)],
}))
}, 2000)
}

render() {
const { items, loading, searchQuery, value } = this.state

return (
<div style={{ margin: 20 }}>
<Segment>
<Header content="Async Dropdown Search" />
<p>Use the field to perform a simulated search.</p>
</Segment>

<Segment>
<Dropdown
fluid
items={items}
loading={loading}
loadingMessage={{
content: <Loader label="Loading..." labelPosition="end" size="larger" />,
}}
multiple
onSearchQueryChange={this.handleSearchQueryChange}
onSelectedChange={this.handleSelectedChange}
placeholder="Try to enter something..."
search
searchQuery={searchQuery}
toggleIndicator={false}
value={value}
/>
<Divider />
<CodeSnippet mode="json" value={this.state} />
</Segment>
</div>
)
}
}

export default AsyncDropdownSearch
1 change: 1 addition & 0 deletions docs/src/prototypes/AsyncDropdownSearch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './AsyncDropdownSearch'
6 changes: 6 additions & 0 deletions docs/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ const Router = () => (
path="/prototype-search-page"
component={require('./prototypes/SearchPage/index').default}
/>,
<DocsLayout
exact
key="/prototype-async-dropdown-search"
path="/prototype-async-dropdown-search"
component={require('./prototypes/AsyncDropdownSearch/index').default}
/>,
<DocsLayout
exact
key="/prototype-popups"
Expand Down
Loading