All Projects → jongold → Further

jongold / Further

Licence: mit
🦄🌈🍄 algebraic style composition for functional UIs

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Further

Styled System
⬢ Style props for rapid UI development
Stars: ✭ 7,126 (+2705.51%)
Mutual labels:  styling, css-in-js
tsstyled
A small, fast, and simple CSS-in-JS solution for React.
Stars: ✭ 52 (-79.53%)
Mutual labels:  styling, css-in-js
Filbert Js
A lightweight(~1kb) css-in-js framework
Stars: ✭ 167 (-34.25%)
Mutual labels:  styling, css-in-js
Otion
Atomic CSS-in-JS with a featherweight runtime
Stars: ✭ 563 (+121.65%)
Mutual labels:  styling, css-in-js
Polished
A lightweight toolset for writing styles in JavaScript ✨
Stars: ✭ 7,074 (+2685.04%)
Mutual labels:  styling, css-in-js
Css In Js
A thorough analysis of all the current CSS-in-JS solutions with SSR & TypeScript support for Next.js
Stars: ✭ 127 (-50%)
Mutual labels:  styling, css-in-js
Fela
State-Driven Styling in JavaScript
Stars: ✭ 2,097 (+725.59%)
Mutual labels:  styling, css-in-js
Phunctional
⚡️ λ PHP functional library focused on simplicity and performance
Stars: ✭ 243 (-4.33%)
Mutual labels:  functional-programming
Arc
React starter kit based on Atomic Design
Stars: ✭ 2,780 (+994.49%)
Mutual labels:  css-in-js
Ink
Ink is a minimal programming language inspired by modern JavaScript and Go, with functional style.
Stars: ✭ 243 (-4.33%)
Mutual labels:  functional-programming
Cats Tagless
Library of utilities for tagless final encoded algebras
Stars: ✭ 238 (-6.3%)
Mutual labels:  functional-programming
Fsharp
The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
Stars: ✭ 2,966 (+1067.72%)
Mutual labels:  functional-programming
Rich Hickey Fanclub
"every time I watch one of his talks I feel like someone has gone in and organized my brain"
Stars: ✭ 2,815 (+1008.27%)
Mutual labels:  functional-programming
Awesome Styled Components
A curated list of awesome styled-components resources 💅
Stars: ✭ 2,869 (+1029.53%)
Mutual labels:  css-in-js
Succinct
Discriminated unions, pattern matching and partial applications for C#
Stars: ✭ 250 (-1.57%)
Mutual labels:  functional-programming
Vcl Styles Utils
Extend and improve the Delphi VCL Styles
Stars: ✭ 238 (-6.3%)
Mutual labels:  styling
Css In Js 101
💈 CSS-in-JS 101: All you need to know
Stars: ✭ 252 (-0.79%)
Mutual labels:  css-in-js
Shen Sources
The Official Shen Sources
Stars: ✭ 248 (-2.36%)
Mutual labels:  functional-programming
Never
Never: statically typed, embeddable functional programming language.
Stars: ✭ 248 (-2.36%)
Mutual labels:  functional-programming
Suddi.github.io
A static single-page application resume-builder developed using React.js and JSON Resume schema (https://suddi.io/)
Stars: ✭ 246 (-3.15%)
Mutual labels:  functional-programming

Further

npm CircleCI FantasyLand

Further adventures down the functional styling rabbit hole leading to the fantasy land

  • 🦄 algebraic style composition
  • 🌈 compose evolutions & transformations
  • 🍄 abstract interaction with props

Usage

import Style from '@jongold/further';
import { add, always, compose as c, evolve } from 'ramda';
import chroma from 'chroma';
import { Touchable, View } from 'react-primitives'; // or react-native etc

// define some abstract style transformations
// bumpFontSize :: CSS -> CSS
const bumpFontSize = evolve({
  fontSize: add(4),
});

// darkenText :: CSS -> CSS
const darkenText = evolve({
  color: c => chroma(a).darken(),
});

// brandify :: CSS -> CSS
const brandify = evolve({
  fontFamily: always('Circular Air Pro'),
});

// and some primitive styles
const boxShadow = {
  boxShadow: '0 2px 3px rgba(0,0,0,.25)',
};

// encapsulate a style that varies on props
const GenericButtonStyle = Style(props => ({
  fontSize: 16,
  fontWeight: 'bold',
  fontFamily: 'SF UI Display'
  backgroundColor: props.primary ? 'green' : 'blue',
  color: 'white',
}));

// and maybe another transform
// that relies on more props
const outlineify = style => Style(props => ({
  ...style,
  border: props.outline ? '1px solid currentColor' : 'none',
  color: props.outline ? style.backgroundColor : style.color,
  backgroundColor: props.outline ? 'transparent' : style.backgroundColor,
}));

// compose some of those transformations
const MyButtonStyle = GenericButtonStyle.map(
  c(bumpFontSize, darkenText, brandify)
).concat(boxShadow).chain(outlineify);

// associative, so could be written as
const MyButtonStyle = GenericButtonStyle
  .map(bumpFontSize)
  .map(darkenText)
  .map(brandify)
  .concat(boxShadow)
  .chain(outlineify);

// Notice that we have passed in any props yet
// so neither GenericButtonStyle nor MyButton
// are complete.

// Let's use it in context. I'm using Flow +
// react-primitives but neither are necessary
type P = {
  children: string,
  primary: bool,
  outline: bool,
  onPress: () => void,
}
const MyButton = (props: P) =>
  <Touchable onPress={props.onPress}>
    <View style={MyButtonStyle.resolve(props)}>
      { props.children }
    </View>
  </Touchable>

<MyButton primary={true} />
// => rendered View has style:
// {
//   fontSize: 20,
//   fontWeight: 'bold',
//   fontFamily: 'Circular Air Pro',
//   backgroundColor: 'darkGreen',
//   color: 'white',
//   boxShadow: '0 2px 3px rgba(0,0,0,.25)',
// }

<MyButton primary={false} outline={true} />
// => rendered View has style:
// {
//   fontSize: 20,
//   fontWeight: 'bold',
//   fontFamily: 'Circular Air Pro',
//   color: 'darkBlue',
//   backgroundColor: 'transparent',
//   border: '1px solid darkBlue',
//   boxShadow: '0 2px 3px rgba(0,0,0,.25)',
// }

Interoperability

Fantasy Land

Further implements FantasyLand 1, FantasyLand 2, FantasyLand 3 compatible Semigroup, Monoid, Functor, Apply, Applicative, Chain, ChainRec and Monad.

Table of contents

Documentation

Type signatures

Hindley-Milner type signatures are used to document functions. Signatures starting with a . refer to "static" functions, whereas signatures starting with a # refer to functions on the prototype.

A list of types used within the signatures:

  • Style - Instances of Style provided by St
  • Props - any JS prop object
  • CSS - raw CSS style objects

Creating Styles

Style

Style :: => (Props -> CSS) -> Style CSS
Style(props => ({
  backgroundColor: props.color,
  fontSize: 16,
});
// Style({ backgroundColor: __color__, fontSize: 16 })

of

.of :: a -> Style a

applicative

Style.of({
  backgroundColor: 'red',
  fontSize: 16,
});
// Style({ backgroundColor: 'red', fontSize: 16, });

Transforming Styles

concat

#concat :: Style a ~> Style a ~> Style a

semigroup

Style.of({ fontWeight: 'bold', fontSize: 14 }).concat({ fontSize: 16, backgroundColor: 'red' })
// Style({ fontWeight: 'bold', fontSize: 16, backgroundColor: 'red' }))

empty

.empty :: () -> Style _

monoid

Style.empty()
// Style({})

map

#map :: Style a ~> (a -> b) -> Style b

functor

Style.of({
  backgroundColor: 'red',
  fontSize: 14
}).map(style => ({
  ...style,
  fontSize: 16
});
// Style({ backgroundColor: 'red, fontSize: 16 }))

Style.of({
  backgroundColor: 'red',
  fontSize: 14
}).map(evolve({
  fontSize: x => x * 2
});
// { backgroundColor: 'red, fontSize: 24 })

chain

#chain :: Style a ~> Style a -> Style a

chain

wip

ap

#ap :: Style (a -> b) ~> Style a -> Style b

apply

Style.of(style => ({
  ...style,
  fontSize: style.fontSize * 2,
}).ap({ color: 'red', fontSize: 14 })
//

Consuming styles

resolve

#resolve :: Style a ~> Props -> CSS
const st = Style(props => ({
  backgroundColor: props.primary ? 'green' : 'gray',
  fontSize: 16,
})).map(evolve({ fontSize: add(2) }))

st.resolve({ title: 'sign up', primary: true })
// { backgroundColor: 'red', fontSize: 18 }

e.g., in a render function

const Button = props =>
  <button style={st.resolve(props)}>
    { props.children }
  </button>
// <button style="background-color: 'red', font-size: 18">sign up</button>

Contributors

Made with love and monads by (emoji key):


Jon Gold

📖 💡 👀

James Baxley

💻

Jake Dawkins

💻

Michael Hurley

👀
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].