The vanilla alternative for writing JSX-based React applications
git clone git://soophie.de/figure
blob: 1a6986a7694a84865ad9703a9af4612b946887c8 (2892 bytes)[doc][blame][raw]
1
<div id="app"></div>3
<script type="module">5
import {useState, createElement} from 'https://cdn.skypack.dev/react';6
import {render} from 'https://cdn.skypack.dev/react-dom';7
import {createTlx} from './lib.js';9
const tlx = createTlx(createElement);11
const Counter = (props) => {12
const [defaultValue, setDefaultValue] = useState(0);13
const { min = 0, max = 999, value = defaultValue, setValue = setDefaultValue } = props ?? {};14
const validate = (value) => {15
if(/^\d+$/.test(value) && parseInt(value) <= max) {16
setValue(parseInt(value));17
}18
}19
return tlx`20
<div style="display: inline-flex; width: 100%; border: 1px solid #a3a3a3; border-radius: 4px; overflow: hidden; height: 40px; box-sizing: border-box;">21
${Button({22
text: '-',23
onClick: () => setValue(value - 1),24
styles: {25
fontSize: '1.2rem',26
borderWidth: '0px 1px 0px 0px'27
},28
disabled: value <= min29
})}30
<input type="text" @input="${(event) => validate(event.target.value)}" value="${value}" style="font-size: 1rem; text-align: center; border: none; flex: 1; min-width: 0; height: 40px; outline: none;">31
${Button({32
text: '+',33
onClick: () => setValue(value + 1),34
styles: {35
fontSize: '1.2rem',36
borderWidth: '0px 0px 0px 1px'37
},38
disabled: value >= max39
})}40
</div>41
`;42
}44
const Button = (props) => {45
const styles = {46
minWidth: '40px',47
height: '40px',48
border: 'none',49
outline: 'none',50
border: '1px solid #a3a3a3',51
backgroundColor: props.disabled ? '#f5f5f5' : '#e5e5e5',52
cursor: props.disabled ? 'default' : 'pointer',53
fontSize: '1rem',54
fontFamily: 'Inter',55
...props.styles56
};57
return tlx`58
<button disabled="${props.disabled}" style="${styles}" @click="${() => props.onClick()}">${props.text}</button>59
`;60
}62
const App = () => {63
const [quantity, setQuantity] = useState(1);64
const isDisabled = quantity <= 0;65
return tlx`66
<div style="margin: 100px; display: flex; width: 150px; flex-direction: column; gap: 15px; align-items: flex-start;">67
${Counter({ value: quantity, setValue: setQuantity })}68
${Button({69
text: 'Add to cart',70
styles: {71
backgroundColor: isDisabled ? '#f5f5f5' : '#f97316',72
borderColor: isDisabled ? '#d4d4d4' : '#c2410c',73
color: isDisabled ? '#a3a3a3' : 'white',74
borderRadius: '4px',75
width: '100%'76
},77
onClick: () => alert(`Added ${quantity} ${quantity > 1 ? 'items' : 'item'} to the cart`),78
disabled: isDisabled79
})}80
</div>81
`;82
}84
const app = document.querySelector('#app');85
render(createElement(App), app);87
</script>