Onda component model
jsx
You can use the jsx
function to create new components using elements or components as reference. It generates an OndaJSXComponent
that inherits and enhances the reference types and styles.
Referencing elements
To reference elements, simply pass its string representation to the function.
const BlueSquare = jsx('div')({
bg: 'blue',
size: 50,
})
render(<BlueSquare />)
Aliasing
jsx
is aliased with any valid JSX.Element
for faster typing.
const BlueSquare = jsx.div({
bg: 'blue',
size: 50,
})
render(<BlueSquare />)
Referencing components
The idea is the same as elements. It will inherit the types and behavior of the passed component.
import { motion } from 'framer-motion'
const Scale = jsx(motion.div)({
bg: 'blue',
size: 50,
})
render(<Scale animate={{ scale: 2 }} transition={{ duration: 0.5 }} />)
Variants
Variants
are props that change the component look. You can set their default values within defaultProps
, as shown in the example below.
const Square = jsx.div({
size: 100,
variants: {
color: {
blue: {
bg: 'blue',
':hover': {
bg: 'blue.hover',
},
},
red: {
bg: 'red',
':hover': {
bg: 'red.hover',
},
},
},
},
})
Square.defaultProps = {
color: 'blue',
}
render(
<Set>
<Square />
<Square color="red" />
</Set>
)
Synching variants
In some cases, you may want to attach styles if two or more variants have specific values. This happens when a variant style depends on other variants, and we call this a variant overlap
. To deal with that you can use the sync
array, which has the type:
Name | Type | Description | Required | Default |
---|---|---|---|---|
csx | StyleObject |
Style to apply if the two variants exists | ||
[k in keyof variants] | keyof variants[k] |
Variants values to sync |
In the example below, we have a square with a solid
or an outline
filling. The square can also be either red
or blue
. We have a variant overlap
here because to set the final style of our square we need to know the value of both fill
and color
variants.
const Square = jsx.div(
{
size: 100,
variants: {
fill: {
outline: {
borderWidth: 2,
borderStyle: 'solid',
},
solid: {
border: 'none',
},
},
color: {
blue: {
bg: 'blue',
':hover': {
bg: 'blue.hover',
},
},
red: {
bg: 'red',
':hover': {
bg: 'red.hover',
},
},
},
},
},
[
{
// if the color is blue and fill outline
color: 'blue',
fill: 'outline',
csx: {
bg: 'transparent',
color: 'blue',
':hover': {
bg: 'blue.secondary.hover',
},
},
},
{
// if the color is red and fill outline
color: 'red',
fill: 'outline',
csx: {
bg: 'transparent',
color: 'red',
':hover': {
bg: 'red.secondary.hover',
},
},
},
]
)
Square.defaultProps = {
color: 'blue',
fill: 'solid',
}
render(
<Set>
<Square />
<Square fill="outline" />
<Square color="red" />
<Square color="red" fill="outline" />
</Set>
)
Options
Options are used to add extra behavior on the component.
interface DisplayOptions {
visible?: boolean
}
const Display = jsx.div({}, {
// you need to declare the used options here.
options: ['visible'],
/**
* options: component options
* props: other props
* system: return of admin-core/useSystem
*/
useOptions(options: DisplayOptions, props, system) {
const { children, ...divProps } = props
const { visible } options
return {
...divProps,
children: visible ? children : null
}
}
})
Display.defaultProps = {
visible: true
}
Polymorphism
Every component generated by jsx
is polymorphic. With the as
prop you can define the component render type, to extend or change its behavior.
const Button = jsx.button({
cursor: 'pointer',
bg: 'blue',
color: 'light.primary',
fontSize: 1,
height: 32,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
paddingX: 2,
borderRadius: 'default',
textAlign: 'center',
})
render(
<Set>
<Button>Button</Button>
<Button as="a" href="">
Button that is a link
</Button>
</Set>
)