jongold / Further
Licence: mit
🦄🌈🍄 algebraic style composition for functional UIs
Stars: ✭ 254
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
Phunctional
⚡️ λ PHP functional library focused on simplicity and performance
Stars: ✭ 243 (-4.33%)
Mutual labels: functional-programming
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
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
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
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
Style.of({
backgroundColor: 'red',
fontSize: 16,
});
// Style({ backgroundColor: 'red', fontSize: 16, });
Transforming Styles
concat
#concat :: Style a ~> Style a ~> Style a
Style.of({ fontWeight: 'bold', fontSize: 14 }).concat({ fontSize: 16, backgroundColor: 'red' })
// Style({ fontWeight: 'bold', fontSize: 16, backgroundColor: 'red' }))
empty
.empty :: () -> Style _
Style.empty()
// Style({})
map
#map :: Style a ~> (a -> b) -> Style b
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
wip
ap
#ap :: Style (a -> b) ~> Style a -> Style b
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].