Coder Social home page Coder Social logo

contiamo / operational-ui Goto Github PK

View Code? Open in Web Editor NEW
258.0 9.0 47.0 40.13 MB

Building blocks for effective operational interfaces

Home Page: https://operational-ui.netlify.com

License: MIT License

JavaScript 0.80% TypeScript 99.20%
component-library design-system react-components visualization

operational-ui's Introduction

Operational UI Components

The @operational/components package contains simple, stateless UI building blocks - your typical input fields, buttons, cards, grids, and so on. See demo and docs.

Getting Started

Install the package via npm or yarn:

npm install @operational/components

Create your first application like so:

import * as React from "react"
import { Button, OperationalUI } from "@operational/components"

// Always wrap your interface in the `OperationalUI` wrapper,
// which does important setup work, and takes a single child element.
// See https://www.npmjs.com/package/%40operational%2Fcomponents
const App = () => (
  <OperationalUI>
    <Button>Hello</Button>
  </OperationalUI>
)

Contributing

To get started contributing, please check out our contributing guidelines.

operational-ui's People

Contributors

adeelibr avatar angarsk8 avatar brunellaa avatar dependabot[bot] avatar dmahlow avatar ericadamski avatar eugengarkusha avatar fabien0102 avatar greenkeeper[bot] avatar grifonas avatar iamshadmirza avatar joshrosenstein avatar kazionovm avatar march213 avatar mehtavishwa30 avatar micha-f avatar michaeldera avatar miqh avatar mpotomin avatar muescha avatar nathanedavis1 avatar nick-barth avatar peterszerzo avatar rimildeyjsr avatar sdabhi23 avatar shershen08 avatar stereobooster avatar tejasq avatar vijayprwyd avatar wptechprodigy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

operational-ui's Issues

Component API style for sizes and colors

This issue is aimed to start a conversation on standardizing component API's around colors and sizes. Attaching two code samples - one with sizes and one with colors - illustrating two different approaches, both of which are in the codebase at the moment. The option 1's have a simpler, and somewhat less accurately typed API. Option 2's are simpler to type-check, but they are more rigorous and verbose. Verboseness is meant to discourage custom sizes and colors while using the library.

/*
 * Size example
 */

// Utilities

const fallbackSize = 16
const isNumber = (a: any): boolean => Number(a) === a

// The Meat

type Size = "small" | "regular" | "large"

// Option 1

type Props1 = {
  size?: Size | number // either a custom color or a ThemeColorName
}

const Component1 = (props: Props1) => {
  if (!props.size) {
    return `No size specified, falling back to ${fallbackSize}.`
  }
  if (isNumber(props.size)) {
    return `We got a custom size: ${props.size}.`
  }
  if (["small", "regular", "large"].indexOf(props.size) > -1) {
    return `Off-the-shelf size ${props.size}.`
  }
  return "There is a problem. I should probably throw a runtime error."
}

// Option 2

type Props2 = {
  size?: Size
  sizeOverride?: number
}

const Component2 = (props: Props2) => {
  if (props.size) {
    return `Off-the-shelf color ${props.size}.`
  }
  if (props.sizeOverride) {
    return `We got a custom size: ${props.sizeOverride}.`
  }
  return `No color specified, falling back to ${fallbackSize}.`
}
/*
 * Color example
 */

// Utilities

const isHex = (s: string): boolean => s.length === 7 && s[0] === "#"
const fallbackColor = "#FFFFFF"

// The Meat

type ThemeColorName = "info" | "warning" | "error" | "black" | "white"

// Option 1

type Props1 = {
  color?: string // either a custom color or a ThemeColorName
}

const Component1 = (props: Props1) => {
  if (!props.color) {
    return `No color specified, falling back to ${fallbackColor}.`
  }
  if (isHex(props.color)) {
    return `We got a custom color: ${props.color}.`
  }
  if (["info", "warning", "error", "black", "white"].indexOf(props.color) > -1) {
    return `Off-the-shelf color ${props.color}.`
  }
  return "There is a problem. I should probably throw a runtime error."
}

// Option 2

type Props2 = {
  color?: ThemeColorName
  colorOverride?: string
}

const Component2 = (props: Props2) => {
  if (props.color) {
    return `Off-the-shelf color ${props.color}.`
  }
  if (props.colorOverride) {
    if (!isHex(props.colorOverride)) {
      return "There is a problem. I should probably throw a runtime error."
    }
    return `We got a custom color: ${props.colorOverride}.`
  }
  return `No color specified, falling back to ${fallbackColor}.`
}

File structure

Suggested directory structure.

// ui-components
▼components
    ▼ Button
        Button.tsx
        Button.style.ts
        ▼ __tests__
            Button.test.tsx
    ▶ InfoTile

// showcase
 ▼pages
    ▼ Buttons
        Buttons.tsx
        ▼ __tests__
            Buttons.test.tsx
        ▼ snippets
            Buttons.simple.snippet.tsx
            Buttons.interesting.snippet.tsx
    ▶ InfoTiles

Tooltip positioning enhancements

In an enhanced version of the tooltips, they would become fixed-positioned right after rerender (once their screen coordinates are known). This will allow them to stay visible even if their parent has overflow hidden.

This is tricky to get right, so this issue is meant as a reminder+discussion spot until we get to the implementation.

Some challenges:

  • scrolling (this behavior is best for hover only-tooltips, maybe there's a way to have those two features be enabled simultaneously).
  • browser compatibility.
  • keeping the API reasonably simple.

Specifying typography

This is a prototype for specifying/standardizing typography in ui-components - take it as a conversation-starter:

const theme: Theme = {
  typography: {
    heading1: {
      fontSize: 13,
      fontWeight: 700,
      textTransform: 'none',
      opacity: 1,
      letterSpacing: '0.2px'
    },
    heading2: {
      fontSize: 13,
      fontWeight: 700,
      textTransform: 'none',
      opacity: 0.6,
      letterSpacing: '0.2px'
    },
    regular: {
      fontSize: 13,
      fontWeight: 400,
      textTransform: 'none',
      opacity: 1,
      letterSpacing: '0.2px'
    },
    small: {
      fontSize: 12,
      fontWeight: 400,
      textTransform: 'none',
      opacity: 1,
      letterSpacing: '0.2px'
    }
  }
}

Thoughts on applying these styles:

  • generate global css snippets that apply heading1 on all h1 tags, regular on all p tags etc. so that you don't have to worry about typography at all (works for some projects better than others).
  • create glamorous.h1(({theme}) => theme.typography.heading1) components - or merge them with other styles while using glamor/glamorous.
  • for quick and dirty things, apply these objects directly as inline-styles.

Readable text colors

screen shot 2017-09-14 at 3 03 52 pm

Looks like the readable text algorithm is putting a black text over a dark green background, which is ultimately less readable than white on green. Propose an explicit algorithm that we can tweak later on, e.g. any hue except the yellows if it's darker than a mid-bright value.

Requiring a theme object

We can save ourselves a lot of unnecessary defensive checking the likes of margin: theme.spacing ? theme.spacing / 2 : 8 if we mandate that code written with the component library is always wrapped in a <ThemeProvider />. We should then export a defaultTheme object that clients can use.

Select issues

Select value validation should be equivalent to the value prop of the Select, not of an Option object passed in.

So basically, I wish it was like this:

<Select value='always' options={[{ id: 0, label: 'sex', value: 'maybe'}, { id: 1, label: 'fun', value: 'always'}]} />

Currently, it is like this:

<Select value={{ id: 1, label: 'fun', value: 'always'}} options={[{ id: 0, label: 'sex', value: 'maybe'}, { id: 1, label: 'fun', value: 'always'}]} />

Let us discuss a friendlier API together. :D

Improve styling

  • All grey stripes between cards (or card and sidebar) should be 16px wide / high
  • Padding right/left of sidebar content should be 12px
  • The caret symbol when pointing downwards needs to be offset 2px from the top when compared to pointing right (in the sidebar)
  • Add border: 3px solid #dadada; around boxes that have non-white backgrounds (e.g. color palette, images on card page, code playgrounds)
  • Default text color: #555f61
  • Headers / emphasis: #373d3f
  • Box shadow for cards should be 0px 1px 2px #d3d1d1
  • Card header bottom border should be #f2f2f2
  • Use font-family: Menlo, Consolas, 'DejaVu Sans Mono', monospace for code playground
  • Use 12px 12px 10px 12px as padding for card header
  • Set code playground background to #282c35
  • Use letter-spacing: normal
  • Default "white" buttons:
    --> border-color: #e2e2e2
    --> border-radius: 2px
    --> padding: 4px 12px
    --> Pressed button / toggled multibutton: box-shadow: inset 0 1px 1px rgba(0,0,0,0.15)
    --> Button font color: #373d3f
    --> Button :hover background-color: #f2f2f2, color: #222
  • In a button group only first and last button should have border-radius (first -> on the left, last -> on the right)

Enhance Pagination

I'd like to request the following changes for the paginator:

  1. A "jump to last page" button after the last skip, kind of like:
    [<<][<] [1] [2] [3] [4] [5] [...204] [>] [>>]
    I understand there is already a "jump to last" button ([>>]), but it would be nice to have a number here so that a user can get an idea of the total number of pages without having to wonder if it goes on forever.

  2. A style more like a group of buttons.

<3

[Pain Point] components are not style-extensible.

Say I have an <Input> and I want it to have its own CSS style. I can't extend it because the component from the library doesn't have/support a css or style prop.

Soooo... I can't do anything to style it :(

Testing methodology

To improve the time spent/value obtained ratio from our tests, I suggest sticking to snapshot-only unit tests for components, and setting up a small number of higher-level integration tests to flush out component behavior.

Integration test ideas:

  • eclectic form: throw a bunch of things including a color picker, multiselect, input etc. in a form. Simulate a bunch of interactions, make sure the right state is obtained at the end.
  • tabs: render a button only if on tab 3. Verify that a click trigger on said button can be reached.

I think this is best kept on a slow burner - the components are shifting quite a bit these days.

Consistent type annotations

What and how should we type annotate? Let's figure out some consistent patterns for:

  • React components/SFCs/elements/nodes
  • dom nodes
  • dom events
  • incomplete-ly annotated third party code

Color name semantics in themes

  • primary => info, secondary => success, tertiary => warning etc.
  • theme.greys.white => theme.colors.white.
  • theme.greys['10'] => theme.colors.grey10 (easier to type and type-safer).

Thoughts?

Add prettier to the precommit hook

@peterszerzo very rightly mentioned that we cannot rely on editors for pretty code so I suggest the following change:

  • We add a .prettierrc file to each package
  • The .prettierrc is common and looks like:
{
  "semi": false,
  "printWidth": 120,
  "parser": "typescript"
}
  • Ideally, we don't use tslint anymore because prettier does what we need it to
  • We add prettier as a devDependency and replace npm run lint to npm run prettier in each package's precommit hook.

Thoughts, @Contiamo/frontend?

Application of styles

Currently, the styling of ui-components mixes CSS-in-JS and regular classnames, which makes the use and authoring of new styles ambiguous, and may expose class name conflicts. Proposing the following change:

const Comp = () =>
  <div>
    <span className="Comp_span"></span>
  </div>
  , styles = {
    display: 'inline-block',
    '& .Comp_span': {
      fontSize: '2rem'
    }
  }

export default glamorous(Comp)(styles)
export { Comp, styles }

to a directly styled component approach:

// Dynamic styles are enabled here
const Container = glamorous.div(props => {
  display: 'inline-block'
})

const Span = glamorous.span({
  fontSize: '2rem'
})

const Comp = () =>
  <Container>
    <Span></Span>
  </Container>

export default Comp

or, if there's a single span:

const Container = glamorous.div({
  display: 'inline-block',
  '& span': {
    fontSize: '2rem'
  }
})

const Comp = () =>
  <Container>
    <span></span>
  </Container>

export default Comp

For tests, this would need a switch from enzyme's render method as opposed to shallow.

Better dev experience for newer components

Currently, when creating new components in ui-components and wanting to document them in the showcase in parallel, one would need to run yarn package:watch in the ui-components folder, and yarn start in the showcase folder as two watch processes.

It would be nice to have one process that watches and updates what is needed in a smarter way.

Select component

Propose the following changes:

  • lift selected state to container component with value and onChange props. Keep open in state etc.
  • require an id for options, and only store id's in the value to remove storage redundancy. Make id's strings so their value can be stored in the option tag without the need for type coercion.
  • make it clearer in the UI that clicking again on a selected option deselects said option (some kind of X).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.