Salad-UI 🚀

npm i --save salad-ui
import SaladUI from 'salad-ui'
<SaladUI.Chart.Area/>

SaladUI is a collection of React components and utility functions that range from translation, to autocomplete and charts. It can be enjoyed as a complete salad using import SaladUI from 'salad-ui' or as its separate ingredients using import {Area} from 'salad-ui.chart'. You can install separate ingredients as npm i --save salad-ui.chart.

Salad-UI will work both in Browser and Server environment - use it in your universal apps!

For optimal old browser compatibility with SaladUI, please include the following polyfill on your page:

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.15/browser-polyfill.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/1.0.0/fetch.min.js"></script>
Code snippets not shown on mobile!

1.x.x release notes

  1. Trans component and translate function should now take parameters in object notation format: {user:{name:'Sam'}}
  2. f is renamed to http
  3. Added formatter.render function to format string templates.
  4. Various updates to the charts, better yLabel formatting.

Chart

  • React Component Area

    const chartData = [{time: new Date('1990-01-02'), value: 1231}]
    
    <SaladUI.Chart.Area
      width={900}
      height={300}
      labelTemplate={data=>`Cats ate ${SaladUI.Lib.formatter.formatCurrency(data.value, 'USD')} worth of fish that day.`}
      data={chartData} width={560}
    />
    0801602403207:51 PM7:58 PM8:04 PM8:11 PM8:17 PM8:24 PM8:30 PM8:36 PM
  • React Component Bar Metric

    <SaladUI.Chart.BarMetric
      label={'Cats'}
      percent={20}
      value={String(20)}
      metricName="%"
    />
    White Cats
    20 %

    Black Cats
    40 %

    Other Cats
    40 %

  • React Component Circle Pie

    <SaladUI.Chart.CirclePie
      width={100}
      height={100}
      strokeWidth={7}
      percent={42}
      strokeColor="rgb(31, 207, 101)"
      fillColor="rgb(31, 207, 101)"
    />
    49%42%72%32%3%

Form

  • React Component Autocomplete

    <Autocomplete/>
  • React Component Checkbox

    <Checkbox/>
    This is a checkbox
  • React Component Switch

    <Switch value={this.state.val} onChange={(val)=>this.setState({val})}/>
    ON
  • React Component Radio

    <RadioGroup/><Radio></RadioGroup>
    This is a Radio element
    This is another Radio element
  • React Component InputText

    <InputText/><InputText textarea/>
  • React Component Select

    let options = [
      {name: 'tofu', value: 'tofu', calories: 400},
      {name: 'bacon', value: 'bacon', calories: 900},
      {name: 'roasted chicken', value: 'chicken', calories: 600},
      {name: 'steak', value: 'steak', calories: 700}
    ]
    <Select
      options={options}
      onChange={(protein)=>this.setState({protein})}>Pick one</Select>
    Pick a protein

    Select without border

    roasted chicken

    Protein: (0cal)

    --

Lib

  • Function http (fetch wrapper)

    http.get('https://api.dailymotion.com/user/spi0n')
    .then(json => console.log(json))
    .catch(err => console.error(err))
    
    http.post('https://api.dailymotion.com/user/spi0n')
    http.delete('https://api.dailymotion.com/user/spi0n')
    
    const api = http.apiFactory('https://api.dailymotion.com', {access_token: 'abc'})
    api.get('/user/spi0n')
  • Function glob

    glob.canUseDom()

    false

  • Function formatter.numberToString

    formatter.numberToString(10782.123)

    11K

  • Function formatter.formatNumber

    formatter.formatNumber(10782.123)

    10,782.12

  • Function formatter.currencyToSymbol

    formatter.currencyToSymbol('USD')

    $

  • Function formatter.formatCurrency

    formatter.formatCurrency(205.12, 'EUR')

    €205.12

  • Function formatter.render

    formatter.render('{greeting}! I am {user.age} years old.', {greeting: 'Hello', user: {age: 32}})

    Hello! I am 32 years old.

  • Function tracking

    tracking.trackPage('SaladUI Demo')
    tracking.trackEvent('eventName', {ga: {label: 'test'}})

Util

  • React Component Alert

    <Alert type="info/error/success/warning">Hello World</Alert>

    This is an alert.

    This is the body of the alert.
    Accept
    Cancel
  • React Component Trans

    <Trans context={{"Hello": "Bonjour"}}>Hello</Trans>
    
    //Can also be used as a plain function (to return a string instead of React Component)
    // Salad.Util.translate(key, args, [pluralform n], [translations])
    SaladUI.Util.translate(
      'There are {elephants} elephants in {city}.',
      {elephants: 24, city: "Hong Kong"},
      24,
      {
        'There are {elephants} elephants in {city}': {
          singular: "Il y a {elephants} elephant Ă  {city}.",
          plural: "Il y a {elephants} elephants Ă  {city}.",
        }
      }
    )
    
    // Or as a factory passing the translations object:
    const Trans = SaladUI.Util.Trans.factory({
      'It is a beautiful day!': 'C'est une belle journée!'
      'The parrot ate the cake.': 'Le perroquet a mangé le gateau.'
    })
    <Trans>It is a beautiful day!</Trans>
    Trans.translate('The parrot ate the cake.')

    Bonjour

    Il y a 24 éléphants à Hong Kong.

    C'est une belle journée!

    Le perroquet a mangé le gateau.

  • React Component TimeAndViews

    <SaladUI.Util.TimeAndViews time={new Date('2010-04-01')} views={40123}/>
    A few months ago • 40K views
  • React Component TextClamp

    <TextClamp>
    This is a long long long long long long long long
    long long long long long long long long long long
    long long long long long long long long long long
    long long long long long long long long long long
    long long long long long long long long long long
    long long long long long long text.
    </TextClamp>
    This is a long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long text.
  • React Component Button

    <Button onPress={()=>alert('ay ay captain')}>Press Me</Button>
    Press Me
    Type primary
    Size small
    DANGER
    Following
    I am longer.
  • React Component ProfilePicture

    <ProfilePicture size={50}/>
  • React Component Tag List

    <TagList items=['tag1','tag2','tag3','tag4','tag5','tag6']/>
    tag1tag2tag3tag4tag5tag6
  • React Component Badges

    <SaladUI.Util.Badge type='live'>Live</SaladUI.Util.Badge>
    <SaladUI.Util.Badge type='verified'></SaladUI.Util.Badge>
    Live00:23

Icon

<SaladUI.Icon
    type="favorite"
    fill="white"
    width={20}
    height={20}/>
alertarrow-leftarrow-downarrow-uparrow-rightbailyblockcalendarcamerachannelchartcheckclosecommentcontestdeleteeditembederrorexpandfacebookfavoritegoogle-plushamburgerhelphomeinfoinfo-signinstagramituneskeylight-onlinklinkedinlistlockmailminusmozaicpinplayplaylistplusreducerevenuereportsearchsettingssharesoundcloudsubscriberssubtitlessuccesstagtimetwitterverified-negativeverifiedviewwarning

Spinner

<SaladUI.Spinner/>

Video

  • React Component Preview

    00:30

    Some video title

    A few months ago • undefined views
    00:30

    A selectable video preview

    A few months ago • undefined views
  • React Component List

    class GridArea extends React.Component{
      render(){
        return (
          <SaladUI.Util.Grid>
            // The videos property is passed down from the Video.List Component
            {
              this.props.videos.map((video,index) =>
                <SaladUI.Video.Preview key={`video.${index}`} type="grid" {...video}/>
              )
            }
          </SaladUI.Util.Grid>
        )
      }
    }
    
    export class LoadMore extends React.Component{
      render(){
        return (
          // The loadMore property is passed down from the Video.List Component
          <SaladUI.Util.Button fullWidth={true} onPress={()=>this.props.loadMore()}>
            Load More
          </SaladUI.Util.Button>
        )
      }
    }
    
    <SaladUI.Video.List
      apiURL="https://api.dailymotion.com"
      limit={10}
      endpoint="/videos"
    >
      <GridArea/>
      <LoadMore/>
    </SaladUI.Video.List>
    Load More
  • React Component List with Preview

    class ListArea extends React.Component{
        render(){
          return (
            <div className="video-list-area">
              {
                this.props.videos.map((video,index) =>
                  <SaladUI.Video.Preview key={`video.${index}`} width={220} type="list" {...video}/>
                )
              }
            </div>
          )
        }
      }
    <SaladUI.Video.List
      apiURL="https://api.dailymotion.com"
      limit={3}
      endpoint="/videos"
    >
      <ListArea/>
      <LoadMore/>
    </SaladUI.Video.List>
    Load More

Overlay

<SaladUI.Util.Overlay
    show=true
    onClose={()}
    closeButton={true}>
    <overlayHeader style={{backgroundColor:'blue'}}>
      This is the header section and the overlay's title
    </overlayHeader>
    <overlayContent>
      This is overlay's content This is overlay's content This is overlay's content This is overlay's content
    </overlayContent>
    <overlayFooter>
      <SaladUI.Util.Button onPress={()=>this.closeOverlay()} style={{marginRight: '10px'}}>Cancel</SaladUI.Util.Button>
      <SaladUI.Util.Button type="primary" onPress={()=>this.closeOverlay()}>Save</SaladUI.Util.Button>
    </overlayFooter>
  </SaladUI.Util.Overlay>
  • Click me!

Transitions

import 'salad-ui.transitions'
  • Transition Duration

    1. transition (default transition)
    2. transition-xs
    3. transition-sm
    4. transition-md
    5. transition-lg
    6. transition-xl
  • Transition Timing

    1. transition-timing-linear
    2. transition-timing-bezier
    3. transition-timing-ease
    4. transition-timing-ease-in-out
  • Scale Effects

    1. scale-in-sm
    2. scale-in-md
    3. scale-in-lg
    4. scale-in-xl
    5. scale-out-sm
    6. scale-out-md
    7. scale-out-lg
    8. scale-out-xl
  • Fade Effects

    1. fade-in
    2. fade-out