The vanilla alternative for writing JSX-based React applications
git clone git://soophie.de/figure
blob: 0c71738c30f1d02b7106ee1f0e9ef991012c31d8 (3122 bytes)[doc][blame][raw]
1
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter&family=Noto+Sans">3
<div id="app"></div>5
<style>7
* {8
font-family: 'Noto Sans', sans-serif;9
}11
body {12
margin: 0;13
}15
</style>17
<script type="module">19
import {useState, createElement} from 'https://cdn.skypack.dev/react';20
import {render} from 'https://cdn.skypack.dev/react-dom';21
import {createTlx, css} from './lib.js';23
const tlx = createTlx(createElement);25
const Button = (props, $slot) => {26
const styles = {27
...css`28
min-width: 40px;29
height: 40px;30
border: none;31
outline: none;32
border: 1px solid #a3a3a3;33
background-color: ${props.disabled ? '#f5f5f5' : '#e5e5e5'};34
cursor: ${props.disabled ? 'default' : 'pointer'};35
font-size: 1rem;36
`,37
...props.styles38
};39
return tlx`40
<button41
disabled="${props.disabled}"42
style="${styles}"43
@click="${() => props.onClick()}"44
>45
${$slot}46
</button>47
`;48
}50
const Counter = (props) => {51
const [defaultValue, setDefaultValue] = useState(0);52
const { min = 0, max = 999, value = defaultValue, setValue = setDefaultValue } = props ?? {};53
const validate = (value) => {54
if(/^\d+$/.test(value) && parseInt(value) <= max) {55
setValue(parseInt(value));56
}57
}58
return tlx`59
<div style="display: inline-flex; width: 100%; border: 1px solid #a3a3a3; border-radius: 4px; overflow: hidden; height: 40px; box-sizing: border-box;">60
${Button({61
onClick: () => setValue(value - 1),62
styles: css`63
font-size: 1.2rem;64
border-width: 0px 1px 0px 0px;65
`,66
disabled: value <= min67
}, '-')}68
<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;">69
${Button({70
onClick: () => setValue(value + 1),71
styles: css`72
font-size: 1.2rem;73
border-width: 0px 0px 0px 1px;74
`,75
disabled: value >= max76
}, '+')}77
</div>78
`;79
}81
const App = () => {82
const [quantity, setQuantity] = useState(1);83
const isDisabled = quantity <= 0;84
return tlx`85
<div style="margin: 100px; display: flex; width: 150px; flex-direction: column; gap: 15px; align-items: flex-start;">86
${Counter({ value: quantity, setValue: setQuantity })}87
${Button({88
styles: css`89
background-color: ${isDisabled ? '#f5f5f5' : '#f97316'};90
border-color: ${isDisabled ? '#d4d4d4' : '#c2410c'};91
color: ${isDisabled ? '#a3a3a3' : '#ffffff'};92
border-radius: 4px;93
width: 100%;94
`,95
onClick: () => alert(`Added ${quantity} ${quantity > 1 ? 'items' : 'item'} to the cart`),96
disabled: isDisabled97
}, 'Add to cart')}98
</div>99
`;100
}102
const app = document.querySelector('#app');103
render(createElement(App), app);105
</script>