summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine-a <sanine.not@pm.me>2021-04-13 11:37:51 -0500
committersanine-a <sanine.not@pm.me>2021-04-13 11:37:51 -0500
commitc9c1b78ed805371615d3ca8b54c86da9a35db8ce (patch)
tree1af9063f2e30392fc039738105f86461dddec576
parentbc594a2d3839d1d0a3cc76eed23ec8535c72f6bf (diff)
implement basic user input and button styling
-rw-r--r--App.js49
-rw-r--r--InputBox.js18
-rw-r--r--StyleButton.js15
-rw-r--r--characters.js2
-rw-r--r--index.html9
-rw-r--r--main.js10
-rw-r--r--style.css57
7 files changed, 148 insertions, 12 deletions
diff --git a/App.js b/App.js
index ebfcae3..cc436b4 100644
--- a/App.js
+++ b/App.js
@@ -1,6 +1,8 @@
let state = {};
let internalState = {};
+const KEY_ENTER = 13;
+
state.currentChar = '你';
function setState(key, value)
@@ -18,19 +20,48 @@ const CurrentCharacter = function({character})
character
);
}
-
+
+function shakeInputBox()
+{
+ setState('inputShaking', true);
+ setTimeout(() => setState('inputShaking', false), 300);
+}
+
const App = function()
{
- const { currentChar } = state;
+ const { currentChar, inputValue, inputShaking } = state;
return h(
'div', {},
[
- h(
- CurrentCharacter,
- {character: currentChar}
- ),
- ]
- );
-}
+ h(CurrentCharacter,
+ { character: currentChar
+ }),
+
+ h(InputBox,
+ { value: inputValue,
+ shouldGrabFocus: true,
+ shaking: inputShaking,
+ handleKeyDown: (e) =>
+ {
+ if (e.keyCode == KEY_ENTER) {
+ console.log(inputValue);
+ }
+ else {
+ setTimeout(() => setState('inputValue', e.target.value), 0);
+ }
+ }
+ }),
+
+ h(StyleButton,
+ {
+ text: 'hello, world',
+ enabled: true,
+ handleClick: () => {
+ console.log('hi there');
+ },
+ }),
+ ]
+ );
+ }
diff --git a/InputBox.js b/InputBox.js
new file mode 100644
index 0000000..61158e0
--- /dev/null
+++ b/InputBox.js
@@ -0,0 +1,18 @@
+const linkEvent = Inferno.linkEvent;
+
+
+function InputBox(props)
+{
+ const { shaking, handleKeyDown } = props;
+
+ const className = shaking ? '.shake' : '';
+
+ return h(
+ `input${className}`,
+ {
+ type: 'text',
+ value: props.value,
+ onKeyDown: handleKeyDown,
+ }
+ );
+}
diff --git a/StyleButton.js b/StyleButton.js
new file mode 100644
index 0000000..806ece6
--- /dev/null
+++ b/StyleButton.js
@@ -0,0 +1,15 @@
+function StyleButton(props)
+{
+ const { enabled, handleClick } = props;
+
+ const className = enabled ? 'StyleButtonEnabled' : 'StyleButtonDisabled';
+
+
+ return h(
+ `div.unselectable.StyleButton.${className}`,
+ {
+ onClick: handleClick,
+ },
+ props.text
+ );
+}
diff --git a/characters.js b/characters.js
index 0ed41aa..a4fb49f 100644
--- a/characters.js
+++ b/characters.js
@@ -79,7 +79,7 @@ let characters = [['的','de'],
['同','tong2'],
['道','dao4'],
['地','di4'],
- ['发','fa3'],
+ ['发','fa1'],
['法','fa3'],
['无','wu2'],
['然','ran2'],
diff --git a/index.html b/index.html
index cb79140..bfe29d4 100644
--- a/index.html
+++ b/index.html
@@ -2,16 +2,21 @@
<html>
<head>
<meta charset="utf-8">
- <title>学汉字</title>
+ <title>学汉字 | sanine.net</title>
<!-- inferno scripts -->
<script src="https://unpkg.com/inferno@7.4.8/dist/inferno.min.js"></script>
<script src="https://unpkg.com/inferno-hyperscript@7.4.8/dist/inferno-hyperscript.min.js"></script>
<!-- local scripts -->
+ <script src="./main.js"></script>
<script src="./characters.js"></script>
+ <script src="./InputBox.js"></script>
+ <script src="./StyleButton.js"></script>
<script src="./App.js"></script>
- <script src="./main.js"></script>
+
+ <!-- styling -->
+ <link href="./style.css" rel="stylesheet">
</head>
<body>
diff --git a/main.js b/main.js
index 0ca765b..72c97a4 100644
--- a/main.js
+++ b/main.js
@@ -2,6 +2,16 @@
const h = Inferno.h;
+function useState(initial) {
+ let state = initial;
+ let setState = (value) => {
+ state = value;
+ render();
+ }
+ return [state, setState];
+}
+
+
function render()
{
Inferno.render(
diff --git a/style.css b/style.css
index 485a1a1..d9873ad 100644
--- a/style.css
+++ b/style.css
@@ -21,3 +21,60 @@ body {
font-size: 200px;
}
+@-webkit-keyframes shake
+{
+ 0%, 100% { transform: translateX(0); }
+ 25%, 75% { transform: translateX(10px); }
+ 50% { transform: translateX(-10px); }
+}
+
+@keyframes shake
+{
+ 0%, 100% { transform: translateX(0); }
+ 25%, 75% { transform: translateX(10px); }
+ 50% { transform: translateX(-10px); }
+}
+
+
+.shake
+{
+ animation-name: shake;
+ animation-duration: 0.3s;
+ animation-iteration-count: 1;
+}
+
+.unselectable
+{
+ -webkit-user-select: none; /* Safari */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* IE10+/Edge */
+ user-select: none; /* Standard */
+}
+
+.StyleButton
+{
+ padding: 10px;
+ border-radius: 8px;
+ border-style: solid;
+ border-width: 2px;
+ display: inline;
+}
+
+
+.StyleButtonEnabled
+{
+ color: white;
+ background-color: #2af;
+}
+
+.StyleButtonEnabled:hover
+{
+ background-color: #6af;
+}
+
+
+.StyleButtonDisabled
+{
+ color: white;
+ background-color: #444;
+}