The vanilla alternative for writing JSX-based React applications
git clone git://soophie.de/figure
blob: 950e26a65624de5e3b9dfc30970a5d60275d6d43 (2846 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 Button = (props, $slot) => {12
const styles = {13
minWidth: '40px',14
height: '40px',15
border: 'none',16
outline: 'none',17
border: '1px solid #a3a3a3',18
backgroundColor: props.disabled ? '#f5f5f5' : '#e5e5e5',19
cursor: props.disabled ? 'default' : 'pointer',20
fontSize: '1rem',21
fontFamily: 'Inter',22
...props.styles23
};24
return tlx`25
<button disabled="${props.disabled}" style="${styles}" @click="${() => props.onClick()}">${$slot}</button>26
`;27
}29
const Counter = (props) => {30
const [defaultValue, setDefaultValue] = useState(0);31
const { min = 0, max = 999, value = defaultValue, setValue = setDefaultValue } = props ?? {};32
const validate = (value) => {33
if(/^\d+$/.test(value) && parseInt(value) <= max) {34
setValue(parseInt(value));35
}36
}37
return tlx`38
<div style="display: inline-flex; width: 100%; border: 1px solid #a3a3a3; border-radius: 4px; overflow: hidden; height: 40px; box-sizing: border-box;">39
${Button({40
onClick: () => setValue(value - 1),41
styles: {42
fontSize: '1.2rem',43
borderWidth: '0px 1px 0px 0px'44
},45
disabled: value <= min46
}, '-')}47
<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;">48
${Button({49
onClick: () => setValue(value + 1),50
styles: {51
fontSize: '1.2rem',52
borderWidth: '0px 0px 0px 1px'53
},54
disabled: value >= max55
}, '+')}56
</div>57
`;58
}60
const App = () => {61
const [quantity, setQuantity] = useState(1);62
const isDisabled = quantity <= 0;63
return tlx`64
<div style="margin: 100px; display: flex; width: 150px; flex-direction: column; gap: 15px; align-items: flex-start;">65
${Counter({ value: quantity, setValue: setQuantity })}66
${Button({67
styles: {68
backgroundColor: isDisabled ? '#f5f5f5' : '#f97316',69
borderColor: isDisabled ? '#d4d4d4' : '#c2410c',70
color: isDisabled ? '#a3a3a3' : 'white',71
borderRadius: '4px',72
width: '100%'73
},74
onClick: () => alert(`Added ${quantity} ${quantity > 1 ? 'items' : 'item'} to the cart`),75
disabled: isDisabled76
}, 'Add to cart')}77
</div>78
`;79
}81
const app = document.querySelector('#app');82
render(createElement(App), app);84
</script>