UNPKG

react-sprucebot

Version:

React components for your Sprucebot Skill 💪🏼

1,193 lines (1,177 loc) 32.6 kB
import React, { Component } from 'react' import ReactDOM from 'react-dom' import styled from 'styled-components' import moment from 'moment-timezone' import Container from '../Container/Container' import BotText from '../BotText/BotText' import Loader from '../Loader/Loader' import { H1, H2, H3, H4, H5, H6, SectionHeading, Paragraph as P, A } from '../Typography/Typography' import Avatar from '../Avatar/Avatar' import Button from '../Button/Button' import Form from '../Form/Form' import Switch from '../Switch/Switch' import InputField from '../InputField/InputField' import SelectField from '../SelectField/SelectField' import { List, ListItem } from '../List/List' import { Tabs, TabPane } from '../Tabs/Tabs' import LinkPile from '../LinkPile/LinkPile' import Pager from '../Pager/Pager' import StatsSlider from '../StatsSlider/StatsSlider' import { GridButton, ButtonGrid } from '../ButtonGrid/ButtonGrid' import Stars from '../Stars/Stars' import ImageCropper from '../ImageCropper/ImageCropper' import Callout from '../Callout/Callout' import Feed from '../Feed/Feed' import TrainingGuide from '../TrainingGuide/TrainingGuide' import Onboarding from '../Onboarding/Onboarding' import Dialog from '../Dialog/Dialog' import Pre from '../Pre/Pre' import Error from '../Error/Error' import Icon from '../Icon/Icon' import IconButton from '../IconButton/IconButton' import ControlButton from '../ControlButton/ControlButton' import TimeInput from '../TimeInput/TimeInput' import DateSelect from '../DateSelect/DateSelect' import DateRangeSelect from '../DateRangeSelect/DateRangeSelect' import skill from '../../skillskit/index' import * as actions from '../../skillskit/store/actions' import reducers from '../../skillskit/store/reducers' import withStore from '../../skillskit/store/withStore' import FormExample from './FormExample' const Dark = styled(Pre)` background-color: #333; padding: 3px; ` const FlexContainer = styled.div` display: flex; justify-content: center; ` const demoGuest = { id: 'b8d62e17-a511-4b9b-ae8a-56710f89af48', role: 'guest', status: 'offline', visits: 1, LocationId: '1975559c-e071-4198-8ab3-eccbeb00e1d0', UserId: 'a2ca3026-ef80-408f-9a39-4ab9fa44a87d', User: { id: 'a2ca3026-ef80-408f-9a39-4ab9fa44a87d', firstName: 'Niki', name: 'Niki R.', profileImageUUID: null, profileImages: { profile60: 'https://hello.sprucebot.com/avatar.jpg', 'profile60@2x': 'https://hello.sprucebot.com/avatar.jpg', profile150: 'https://hello.sprucebot.com/avatar.jpg', 'profile150@2x': 'https://hello.sprucebot.com/avatar.jpg' }, defaultProfileImages: { profile60: 'https://s3.amazonaws.com/sprucebot-dev/default-profile--X60.jpg', 'profile60@2x': 'https://s3.amazonaws.com/sprucebot-dev/default-profile--X60@2x.jpg', profile150: 'https://s3.amazonaws.com/sprucebot-dev/default-profile--X150.jpg', 'profile150@2x': 'https://s3.amazonaws.com/sprucebot-dev/default-profile--X150@2x.jpg' } }, isConnected: true, lastRecordedVisit: '2017-12-01T23:05:35.705Z', updatedAt: '2017-12-02T00:06:05.448Z', Location: { id: '1975559c-e071-4198-8ab3-eccbeb00e1d0', name: 'Spruce', addressLine1: '4347 Tennyson St', addressLine2: null, addressCity: 'Denver', addressState: 'CO', addressZip: '80212', addressCountry: 'US', geo: { lat: 39.775644, lng: -105.044258 }, OrganizationId: 'fcdd548b-fe3b-42dc-8c66-6810411cd84d' } } let NOW if (process.env.NODE_ENV === 'test') { NOW = moment(946738800000).tz('America/Los_Angeles') // Snapshot testing requires an unchanging date } else { NOW = new Date() } class Styleguide extends Component { constructor(props) { super(props) this.state = { calloutOn: false, errorMessage: '', showAlert: false } this.didCompleteOnboarding = this.didCompleteOnboarding.bind(this) } didCompleteOnboarding() { const { onboardingComplete } = this.props.onboarding if (!onboardingComplete) { this.props.actions.onboarding.finishOnboarding() console.log( 'Posting to your database that you completed onboarding. Check your Skill Data now!' ) } else { console.log( "You've already completed the onboarding. Check your Skill Data now!" ) } } render() { const HR = <hr style="border-top-width:10px;" /> const { calloutOn } = this.state return ( <div> <H1>Importing Components</H1> <Container> <BotText> All the components you need to build your skill are available in the 'react-sprucebot' module. Any modules you create yourself are subject to rejection from the Skills Marketplace. </BotText> <Pre>{`import { Container, BotText, Loader, H1, H2, H3, H4, H5, H6, SectionHeading, Paragraph as P, A, Avatar, Button, Form, Switch, InputField, SelectField, SubmitWrapper, List, ListItem, Tabs, TabPane, LinkPile, Pager, StatsSlider, ButtonGrid, GridButton, Stars, ImageCropper, Callout, Feed, TrainingGuide, Dialog, Icon, IconButton, ControlButton } from 'react-sprucebot'`}</Pre> </Container> <H1>Headings</H1> <Container> <BotText> Notice the use of the Component with a capitalized tag, e.g. 'H' vs 'h'. This is intentional and is actively enforced. </BotText> <H1>I'm an H1</H1> <Pre>{`<H1>I'm an H1</H1>`}</Pre> <H2>I'm an H2</H2> <Pre>{`<H2>I'm an H2</H2>`}</Pre> <H3>I'm an H3</H3> <Pre>{`<H3>I'm an H3</H3>`}</Pre> <H4>I'm an H4</H4> <Pre>{`<H4>I'm an H4</H4>`}</Pre> <H5>I'm an H5</H5> <Pre>{`<H5>I'm an H5</H5>`}</Pre> <H6>I'm an H6</H6> <Pre>{`<H6>I'm an H6</H6>`}</Pre> <P>I'm a paragraph of some text</P> <Pre>{`<P>I'm a paragraph of some text</P>`}</Pre> <A href="#">I'm an anchor tag</A> <Pre>{`<A href="#">I'm an anchor tag</A>`}</Pre> <SectionHeading>Section Heading</SectionHeading> <Pre>{`<SectionHeading>Section Heading</SectionHeading>`}</Pre> <BotText> Use SectionHeading to break up sections of your page and to label forms, similar to a fieldset. </BotText> </Container> <H1>Sub Headings</H1> <Container> <H1 with_subheader>Header</H1> <H2 subheader>Sub Headings</H2> <Pre >{`<H1 with_subheader>Header</H1>\n<H2 subheader>Sub Headings</H2>`}</Pre> </Container> <H1>Bot Text</H1> <Container> <BotText> I'm some bot text. I'm great for quick hints, tips, shout outs, etc. This text comes right from Sprucebot, so make sure it's on brand. </BotText> <Pre >{`<BotText>I'm some bot text. I'm great for quick hints, tips, shout outs, etc. This text comes right from Sprucebot, so make sure it's on brand.</BotText>`}</Pre> </Container> <H1>Paragraphs</H1> <Container> <P>I'm a normal paragraph tag</P> <Pre>{`<P>I'm a normal paragraph tag</P>`}</Pre> <P fine>I'm some fine print</P> <Pre>{`<P fine>I'm some fine print</P>`}</Pre> </Container> <H1>Top Avatar</H1> <Container> <BotText> Avatars usually go next to users when output in a list. Adding the "top" property will make it big and center. Great for the tops of profile or dashboard pages. </BotText> <Avatar top image="https://hello.sprucebot.com/avatar.jpg" /> <Pre >{`<Avatar top image="https://hello.sprucebot.com/avatar.jpg" />`}</Pre> </Container> <H1 ref={ref => { this.ref = ref }} > Buttons </H1> <Container> <Button primary>I'm a primary button</Button> <Pre>{`<Button primary>I'm a primary button</Button>`}</Pre> <Button primary disabled> I'm a primary disabled button </Button> <Pre >{`<Button primary disabled>I'm a primary disabled button</Button>`}</Pre> <Button secondary>I'm a secondary button</Button> <Pre>{`<Button secondary>I'm a secondary button</Button>`}</Pre> <Button secondary disabled> I'm a secondary disabled button </Button> <Pre >{`<Button secondary disabled>I'm a secondary disabled button</Button>`}</Pre> <Button alt>I'm an alt button</Button> <Pre>{`<Button alt>I'm an alt button</Button>`}</Pre> <Button alt disabled> I'm an alt disabled button </Button> <Pre >{`<Button alt disabled>I'm an alt disabled button</Button>`}</Pre> <Button secondary alt> I'm a secondary alt button </Button> <Pre >{`<Button secondary alt >I'm a secondary alt button</Button>`}</Pre> <Button secondary alt disabled> I'm a secondary alt disabled button </Button> <Pre >{`<Button secondary alt disabled>I'm a secondary alt disabled button</Button>`}</Pre> <Button caution>I'm a caution button</Button> <Pre>{`<Button caution>I'm a caution button</Button>`}</Pre> <Button link>I'm a button link</Button> <Pre>{`<Button link>I'm a button link</Button>`}</Pre> </Container> <H1>Link Buttons</H1> <BotText> Buttons can also be turned into links by setting the "href". Optional options include setting "target", or "router" </BotText> <Container> <Pre >{`<Button primary href="https://sprucebot.com">I'm a primary button turned link</Button>`}</Pre> <Button primary href="https://sprucebot.com"> I'm a primary button turned link </Button> <Pre >{`<Button primary href="https://sprucebot.com" target="_blank">I'll open in a new window</Button>`}</Pre> <Button primary href="https://sprucebot.com" target="_blank"> I'll open in a new window </Button> <Pre >{`import Router from 'next/router'\n\n<Button primary href="/styleguide" router={Router}>I'll use next.js router.push() to change url</Button>`}</Pre> <Button primary href="/"> I'll use next.js router.push() to change url </Button> </Container> <H1>Icons</H1> <Container className="icon__button__container"> <BotText> Icons and Icon Buttons have the option to display an icon using Material Icons. Check out https://material.io/icons/. To use an icon, just enter the icon name as the child of the button. </BotText> <Icon>mood</Icon> <Pre>{`<Icon>mood</Icon>`}</Pre> <IconButton>place</IconButton> <Pre >{`<IconButton onClick={/* Handle Click */}>place</IconButton>`}</Pre> </Container> <H1>Control Buttons</H1> <Container> <BotText> Control Buttons have the option to display a right or left icon using Material Icons. Check out https://material.io/icons/. To use an icon, just enter the icon name as a value for the iconLeft or iconRight prop. You can also pass an href to render the button as a link! </BotText> <ControlButton>I'm a control button</ControlButton> <Pre>{`<ControlButton>I'm a control button</ControlButton>`}</Pre> <ControlButton iconLeft="favorite">I have a left icon</ControlButton> <Pre >{`<ControlButton iconLeft="favorite">I have a left icon</ControlButton>`}</Pre> <ControlButton iconRight="edit">I have a right icon</ControlButton> <Pre >{`<ControlButton iconRight="edit">I have a right icon</ControlButton>`}</Pre> <ControlButton iconRight="🤖" href="https://sprucebot.com"> I'm a link </ControlButton> <Pre >{`<ControlButton iconRight="🤖" href="https://sprucebot.com">I'm a link</ControlButton>`}</Pre> </Container> <H1>Loaders</H1> <Container> <BotText> Loaders can be dark or light. Default, they are dark. But, if you need to put a loader on a dark dark background, set dark={false}. </BotText> <Loader /> <Pre>{`<Loader />`}</Pre> <Dark> <Loader dark={false} /> </Dark> <Pre>{`<Loader dark={false} />`}</Pre> <Button busy>Content does not matter</Button> <Pre>{`<Button busy>Content does not matter</Button>`}</Pre> </Container> <H1>Switches</H1> <Container> <Switch onChange={(on, e) => { console.log('on:', on, 'event:', e) }} /> <Pre>{`<Switch onChange={(on, e) => { console.log('on:', on, 'event:', e) }} />`}</Pre> <Switch on /> <Pre>{`<Switch on />`}</Pre> </Container> <H1>Date Select</H1> <Container> <BotText> Date Select allows for the selection of a single date and returns a moment object. Custom props allow blocked dates, default values, and initial visible months. </BotText> <Pre>{`<DateSelect allowPastDates bypassDaysBlocked onDateSelect={(date) => { console.log(date) }} defaultDate={moment('2018-08-10')} initialVisibleMonth={() => moment('2018-08-10')} />`}</Pre> <FlexContainer> <DateSelect allowPastDates bypassDaysBlocked onDateSelect={date => { console.log(date) }} defaultDate={moment('2018-08-10')} initialVisibleMonth={() => moment('2018-08-10')} /> </FlexContainer> </Container> <H1>Date Range Select</H1> <Container> <BotText> Date Range Select allows for the selection of a range of dates via choosing a start and end date, returning a moment object for each. Custom props allow for the viewing of outside month days, selection of an entire current week, and default date selection. </BotText> <Pre>{`<DateRangeSelect allowPastDates bypassDaysBlocked onDatesChange={(startDate, endDate) => { console.log(startDate, endDate) }} numberOfMonths={1} setDefaultDates defaultStartDate={moment('2018-03-28')} defaultEndDate={moment()} />`}</Pre> <FlexContainer> <DateRangeSelect allowPastDates bypassDaysBlocked onDatesChange={(startDate, endDate) => { console.log(startDate, endDate) }} numberOfMonths={1} setDefaultDates defaultStartDate={moment('2018-03-28')} defaultEndDate={moment()} /> </FlexContainer> <Pre>{`<DateRangeSelect allowPastDates bypassDaysBlocked onDatesChange={(startDate, endDate) => { console.log(startDate, endDate) }} numberOfMonths={2} currentWeek enableOutsideDays initialVisibleMonth={() => moment('2018-10-31')} orientation={'vertical'} />`}</Pre> <FlexContainer> <DateRangeSelect allowPastDates bypassDaysBlocked onDatesChange={(startDate, endDate) => { console.log(startDate, endDate) }} numberOfMonths={2} currentWeek enableOutsideDays initialVisibleMonth={() => moment('2018-10-31')} orientation={'vertical'} /> </FlexContainer> </Container> <H1>Time Input</H1> <Container> <BotText> The Time Input is a cross-browser compatible implementation for capturing a time. </BotText> <Pre>{`<TimeInput defaultValue="22:15" onChange={newValue => console.log(\`Time Input Changed to: \${newValue}\`) } ref={ref => (this.timeInput = ref)} />`}</Pre> <TimeInput defaultValue="22:15" onChange={newValue => console.log(`Time Input Changed to: ${newValue}`) } ref={ref => (this.timeInput = ref)} /> </Container> <H1>Redux Forms</H1> <Container> <FormExample /> </Container> <H1>Lists</H1> <Container> <SectionHeading>A Friend List</SectionHeading> <BotText> Lists are very useful for showing guests, teammates, etc. </BotText> <List> <ListItem title="Taylor" subtitle="Last Visit: Today" rightTitle="Owner" rightSubtitle="Visits: 7" avatar="https://hello.sprucebot.com/avatar.jpg" /> <ListItem online={false} title="Ryan" subtitle="Last Visit: 10 days ago" rightTitle="Owner" rightSubtitle="Visits: 7" avatar="https://hello.sprucebot.com/avatar.jpg" /> </List> <Pre>{`<List> <ListItem title="Taylor" subtitle="Last Visit: Today" rightTitle="Owner" rightSubtitle="Visits: 7" avatar="https://hello.sprucebot.com/avatar.jpg" /> <ListItem online={false} title="Ryan" subtitle="Last Visit: 10 days ago" rightTitle="Owner" rightSubtitle="Visits: 7" avatar="https://hello.sprucebot.com/avatar.jpg" /> </List>`}</Pre> <SectionHeading>A Flexible List!</SectionHeading> <BotText> But, lists can do more than that! Actually, a LOT more than that! </BotText> <List> <ListItem>This is the most basic list item.</ListItem> <ListItem title="Awesome title!" subtitle="Fantastic subtitle!" rightInput={ <Button remove onClick={e => { console.log('event:', e) }} /> } /> <ListItem rightInput={<Switch />}>I can even do switches!</ListItem> <ListItem> <InputField label="An input!" input={{ value: '' }} meta={{}} /> </ListItem> <ListItem> <SelectField label="And a SelectField!" input={{ value: '' }} meta={{}} > <option>Nuke 'em Rico</option> <option>With pleasure!</option> </SelectField> </ListItem> </List> <Pre>{`<List> <ListItem>This is the most basic list item.</ListItem> <ListItem title="Awesome title!" subtitle="Fantastic subtitle!" rightInput={ <Button remove onClick={e => { console.log('event:', e) }} /> } /> <ListItem rightInput={<Switch />}>I can even do switches!</ListItem> <ListItem> <InputField label="An input!" input={{value: 'val', onChange: () => console.log('onChange!')}} /> </ListItem> <ListItem> <Select label="And a select!"> <option>Nuke 'em Rico</option> <option>With pleasure!</option> </Select> </ListItem> </List>`}</Pre> </Container> <H1>Tabs</H1> <Container> <Tabs onChange={(idx, e) => { console.log('tab:', idx, 'event:', e) }} > <TabPane title="First">First Pane</TabPane> {!this.state.hideSecondPane && ( <TabPane selected title="Second"> <BotText> Tabs are fantastic! You can use them so easily! </BotText> </TabPane> )} <TabPane title="Third"> <BotText>Tabs can be dynamically hidden and shown!</BotText> <List> <ListItem title="Show Second Tab" rightInput={ <Switch on={true} onChange={on => this.setState({ hideSecondPane: !on })} /> } /> </List> </TabPane> </Tabs> <Pre>{`<Tabs onChange={(idx, e) => { console.log('tab:', idx, 'event:', e) }} > <TabPane title="First">First Pane</TabPane> <TabPane selected title="Second"> <BotText>Tabs are fantastic! You can use them so easily!</BotText> </TabPane> <TabPane title="Third">Third Pane</TabPane> </Tabs>`}</Pre> </Container> <H1>Link Pile</H1> <Container> <BotText> LinkPile's are great for dashboards or control panels. It shrinks the margin between buttons to make them look more cohesive. </BotText> <SectionHeading>Controls</SectionHeading> <LinkPile> <Button primary>Button 1</Button> <Button alt>Button 2</Button> <Button secondary>Button 3</Button> <Button secondary alt> Button 4 </Button> </LinkPile> <Pre>{`<LinkPile> <Button primary>Button 1</Button> <Button alt>Button 2</Button> <Button secondary>Button 3</Button> <Button secondary alt> Button 4 </Button> </LinkPile>`}</Pre> </Container> <H1>Pager</H1> <Container> <BotText> The pager is pretty simple. It will track your page (zero based), but you'll need to implement `onChange`` to make your API requests. Also, don't forget to add `totalPages`. </BotText> <Pager totalPages={5} titles={page => ['Page 1', 'Custom', 'What the?', 'You know', 'What'][page] } onChange={(page, e) => { console.log('page:', page, 'event:', e) }} /> <Pre>{`<Pager totalPages={5} titles={page => ['Page 1', 'Custom', 'What the?', 'You know', 'What'][page]} onChange={(page, e) => { console.log('page:', page, 'event:', e) }} />`}</Pre> </Container> <H1>Stats Slider</H1> <Container> <SectionHeading>KPI's</SectionHeading> <StatsSlider stats={[ { dir: 1, title: 'Hourly', value: '$23.50' }, { dir: -1, title: 'Services', value: 10 }, { dir: 1, title: 'Avg. Ticket', value: '$25.23' }, { dir: 0, title: 'Returns', value: 0 } ]} /> <Pre>{`<StatsSlider stats={[ { dir: 1, title: 'Hourly', value: '$23.50' }, { dir: -1, title: 'Services', value: 10 }, { dir: 1, title: 'Avg. Ticket', value: '$25.23' }, { dir: 0, title: 'Returns', value: 0 } ]} />`}</Pre> </Container> <H1>Button Grid</H1> <Container> <SectionHeading>Select Your Options</SectionHeading> <BotText> Set the line-height of .btn_grid .btn to control height of button. The text will stay centered. </BotText> <ButtonGrid> <GridButton subtitle="It's good">Option 1</GridButton> <GridButton subtitle="It's better!">Option 2</GridButton> <GridButton subtitle="Def worth a look" selected> Option 3 </GridButton> </ButtonGrid> <Pre>{`<ButtonGrid> <GridButton subtitle="It's good">Option 1</GridButton> <GridButton subtitle="It's better!">Option 2</GridButton> <GridButton subtitle="Def worth a look" selected> Option 3 </GridButton> </ButtonGrid>`}</Pre> </Container> <H1>Stars</H1> <Container> <BotText>Please take a moment to rate this rating component.</BotText> <Stars max={4} score={2} static={false} onChange={(score, e) => { console.log('score:', score, 'event:', e) }} /> <Pre>{`<Stars max={4} score={2} static={false} onChange={(score, e) => { console.log('score:', score, 'event:', e) }} />`}</Pre> <BotText> You can also make Stars static so the rating cannot be changed! </BotText> <Stars max={4} score={2} static={true} onChange={(score, e) => { console.log('score:', score, 'event:', e) }} /> <Pre>{`<Stars max={4} score={2} static={true} onChange={(score, e) => { console.log('score:', score, 'event:', e) }} />`}</Pre> </Container> <H1>Image Cropper</H1> <Container> <BotText> Our ImageCropper is currently using{' '} <a onClick={e => e.stopPropagation()} href="https://github.com/DominicTobias/react-image-crop" > react-image-crop </a>. Tap the button below and give it a shot. </BotText> <ImageCropper tapToCrop={true} src="https://s3.amazonaws.com/sprucebot/ticket.png" onSave={img => console.log(img)} crop={{ x: 25, y: 25, width: 50, height: 50 }} /> <Pre>{`<ImageCropper tapToCrop={true} src="https://s3.amazonaws.com/sprucebot/ticket.png" onSave={img => console.log(img)} crop={{ x: 25, y: 25, width: 50, height: 50 }} />`}</Pre> </Container> <H1>Callouts</H1> <Container> <BotText> If you have some information you need to call out (think modal dialog), you can use the {`<Callout />`} component. </BotText> <Callout on={calloutOn}> <H2>Some important sub-form</H2> <BotText> Things like nested forms or multi-step processes benefit greatly from a callout. It lets you see where you were, but brings focus to what you're about to do. </BotText> <List> <ListItem rightInput={ <Switch onChange={calloutOn => this.setState({ calloutOn })} /> } > Try the call out! -> </ListItem> </List> </Callout> <Pre>{`<Callout on={calloutOn}> <H2>Call this out</H2> <BotText> Things like nested forms or multi-step processes benefit greatly from a callout. It lets you see where you were, but brings focus to what you're about to do. </BotText> <List> <ListItem rightInput={ <Switch onChange={calloutOn => this.setState({ calloutOn })} /> } > Try the call out! -> </ListItem> </List> </Callout>`}</Pre> </Container> <H1>The Feed</H1> <Container> <BotText> The Feed is used by nearly every Skill to visualize events and facilitate conversation around those events. </BotText> <Feed data={[ { createdAt: moment(NOW).subtract(34, 'hour'), id: 'bbc55a55-2e13-4322-a2c5-0fec1abc79be', message: 'Randy C. has arrived! 💥 This <FeedItem /> has bigAvatar set to true.', user: demoGuest, bigAvatar: true, attachments: [ { title: 'Membership level', value: 'Gold' }, { title: 'Total Points', value: 1253 } ] }, { createdAt: moment(NOW).subtract(25, 'hour'), id: 'bbc55a55-2e13-4372-a2c5-0fec1abc79ee', message: 'Ryan J. has arrived! 💥 bigAvatar is not true.', user: demoGuest, attachments: [ { title: 'Membership level', value: 'Turquoise' }, { title: 'Total Points', value: 2393 }, { title: 'Favorite Color', value: 'blue' }, { title: 'Note', fullWidth: true, value: '"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus sed dolor ac felis scelerisque hendrerit ac et dui. Sed vel tortor vitae magna luctus aliquam sit amet ut eros. Duis et viverra nulla, et mattis nunc." - Taylor R. Sept. 3rd' } ] }, { createdAt: NOW, id: 'bbc55a55-2e13-4322-a2c5-0fec1dabc79ee', message: 'Shane M. has arrived! 💥 We also added more to this message to demo long alerts.', user: demoGuest, attachments: [ { title: 'Membership level', value: 'Platinum' }, { title: 'Total Points', value: 5302 }, { title: 'Visits', value: 5 }, { title: 'Idle chit-chat', value: 'A little' } ] } ]} /> <Pre>{`<Feed data={[ { createdAt: moment(NOW).subtract(34, 'hour'), id: 'bbc55a55-2e13-4322-a2c5-0fec1abc79be', message: 'Randy C. has arrived! 💥 This <FeedItem /> has bigAvatar set to true.', user: demoGuest, bigAvatar: true, attachments: [ { title: 'Membership level', value: 'Gold' }, { title: 'Total Points', value: 1253 } ] }, { createdAt: moment(NOW).subtract(25, 'hour'), id: 'bbc55a55-2e13-4372-a2c5-0fec1abc79ee', message: 'Ryan J. has arrived! 💥 bigAvatar is not true.', user: demoGuest, attachments: [ { title: 'Membership level', value: 'Turquoise' }, { title: 'Total Points', value: 2393 }, { title: 'Favorite Color', value: 'blue' }, { title: 'Note', fullWidth: true, value: '"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus sed dolor ac felis scelerisque hendrerit ac et dui. Sed vel tortor vitae magna luctus aliquam sit amet ut eros. Duis et viverra nulla, et mattis nunc." - Taylor R. Sept. 3rd' } ] }, { createdAt: NOW, id: 'bbc55a55-2e13-4322-a2c5-0fec1dabc79ee', message: 'Shane M. has arrived! 💥 We also added more to this message to demo long alerts.', user: demoGuest, attachments: [ { title: 'Membership level', value: 'Platinum' }, { title: 'Total Points', value: 5302 }, { title: 'Visits', value: 5 }, { title: 'Idle chit-chat', value: 'A little' } ] } ]} />`}</Pre> </Container> <H1>Training Guide</H1> <Container> <TrainingGuide onComplete={() => alert('Done!')} steps={[ 'This is a training guide.', 'It "guides" you through many steps.', 'One at a time', 'and the last one shows a done.' ]} /> </Container> <Container> <Onboarding heading={'Onboarding'} steps={[ 'This is an onboarding component.', 'It has a heading.', 'And "guides" you through the steps like the TrainingGuide.', 'You can also change the label of the done button.', 'Additionally, you can pass a boolean prop to say if onboarding has been completed.', 'If the owner/teammate has done onboarding already, all of the messages will be displayed.' ]} onComplete={this.didCompleteOnboarding} doneButtonLabel={'Finish'} onboardingComplete={this.props.onboarding.onboardingComplete} /> <Pre> {`<Onboarding heading={'Onboarding'} steps={[ 'This is an onboarding component.', 'It has a heading', 'And "guides" you through the steps like the TrainingGuide', 'You can also change the label of the done button.', 'Additionally, you can pass a boolean prop to say if onboarding has been completed.', 'If the owner/teammate has done onboarding already, all of the messages will be displayed.' ]} onComplete={this.didCompleteOnboarding} doneButtonLabel={'Finish'} onboardingComplete={this.props.onboarding.onboardingComplete} />`} </Pre> </Container> <H1>Dialogs</H1> <Container> <BotText> Dialogs are always shown modally. So, you can use them as alerts, confirmation dialogs, popups, etc. </BotText> <List> <ListItem title="Showing as an alert" subtitle="You can drop in a button to hide it too" rightInput={ <Button alt type="button" onClick={() => this.setState({ showAlert: true })} > Show Alert </Button> } /> </List> <Dialog show={this.state.showAlert}> <BotText>Use BotText to display any content in the alert.</BotText> <Button type="button" onClick={() => this.setState({ showAlert: false })} > Okay </Button> </Dialog> <Pre>{`<Dialog show={this.state.showAlert}> <BotText>Use BotText to display any content in the alert.</BotText> <Button type="button" onClick={() => this.setState({ showAlert: false })} > Okay </Button> </Dialog>`}</Pre> </Container> <H1>Error</H1> <Container> <Button onClick={() => this.setState({ errorMessage: 'There was an error. Please try again' }) } > {'Show Error Message'} </Button> <Error errorMessage={this.state.errorMessage} closeErrorDialog={() => this.setState({ errorMessage: '' })} closeErrorDialogTxt={'Sounds good!'} /> <Pre>{`<Error errorMessage={this.state.errorMessage} closeErrorDialog={() => this.setState({ errorMessage: '' })} closeErrorDialogTxt={'Sounds good!'} />`}</Pre> </Container> <H1>Scroll To Method</H1> <Container> <BotText> {`This method allows the user to scroll to any position they want. The default is to the top of the page, but the user can pass in a number or component using ReactDOM to find the ref's offsetTop as well`} </BotText> <Button onClick={() => { skill.scrollTo() }} > {'Default Scroll To Top'} </Button> <Pre>{`<Button onClick={() => { skill.scrollTo() }} > {'Scroll To The Top'} </Button>`}</Pre> <Button onClick={() => { skill.scrollTo(2600) }} > {'Scroll To A Number'} </Button> <Pre>{`<Button onClick={() => { skill.scrollTo(2550) }} > {'Scroll To The Top'} </Button>`}</Pre> <Button onClick={() => { skill.scrollTo(ReactDOM.findDOMNode(this.ref).offsetTop) }} > {'Scroll To The Buttons Section'} </Button> <Pre>{`<Button onClick={() => { skill.scrollTo(ReactDOM.findDOMNode(this.ref).offsetTop) }} > {'Scroll To The Top'} </Button>`}</Pre> </Container> </div> ) } } export default withStore(Styleguide, { actions, reducers, config: { SERVER_HOST: 'https://example.com' } })