Skip to content

Instantly share code, notes, and snippets.

@LukasFB
Created August 6, 2020 01:34
Show Gist options
  • Save LukasFB/2a58b496fc7469db86f2858a1ea05568 to your computer and use it in GitHub Desktop.
Save LukasFB/2a58b496fc7469db86f2858a1ea05568 to your computer and use it in GitHub Desktop.
import React, { useState } from "react"
import PropTypes from 'prop-types'
import "./input.css"
import TypingIndicator from "./TypingIndicator"
const input = (props) => {
const styles = ["plank", "staggered", "split"]
const [stateIsFocused, setStateIsFocused] = useState(false)
const [stateIsClear, setStateIsClear] = useState(props.initialValue === "")
const [stateTypingTrigger, setStateTypingTrigger] = useState("")
const [stateStyle, setStateStyle] = useState(styles[Math.floor(Math.random() * styles.length)])
const handleChange = e => {
const value = e.target.value
setStateTypingTrigger(Math.random())
if (value === "") {
setStateIsClear(true)
} else {
setStateIsClear(false)
}
props.onChange(value)
}
const classes = ["kc-input"]
if (stateIsFocused) classes.push("kc-input__focused")
if (stateIsClear && !stateIsFocused) classes.push("kc-input__clear")
return <div className={classes.join(" ")}>
<div className={"kc-input_label"}>{props.label}</div>
<div className={"kc-input_typing-wrapper"}>
{
stateIsFocused
? <TypingIndicator
trigger={stateTypingTrigger}
style={stateStyle}
/>
: null
}
</div>
<input
autoComplete={"off"}
onChange={handleChange}
onFocus={() => {
setStateStyle(styles[Math.floor(Math.random() * styles.length)])
setStateIsFocused(true)
}}
onBlur={() => setStateIsFocused(false)}
/>
</div>
}
input.propTypes = {
onChange: PropTypes.func.isRequired,
label: PropTypes.string.isRequired,
initialValue: PropTypes.string,
}
input.defaultProps = {
initialValue: "",
}
export default input
.kc-input
position: relative
background-color: rgba(white, 0.2)
transition: all 0.2s
padding: 10px 10px
padding-top: 25px
.kc-input_label
position: absolute
top: 0px
font-size: 14px
transition: all 0.3s
.kc-input_typing-wrapper
position: absolute
bottom: 39px
right: 10px
opacity: 0
transition: all 0.2s
input
width: 100%
background-color: transparent
border: none
border-bottom: 1px solid #ccc
transition: all 0.3s
outline: none
&.kc-input__focused
input
border-bottom-color: $color
.kc-input_typing-wrapper
opacity: 1
&.kc-input__clear
.kc-input_label
position: absolute
top: 16px
font-size: 19px
import React, { useEffect, useState } from "react"
import PropTypes from 'prop-types'
import "./typingIndicator.css"
import TypingIndicatorRow from "./TypingIndicatorRow"
const typingIndicator = (props) => {
let rows = ["o1", "o2", "o3", "o4"]
switch (props.style) {
case "staggered":
rows = ["s1", "s2", "s3", "s4"]
break
case "split":
rows = ["p1", "p2", "p3", "p4"]
break
}
const [stateTriggers, setStateTriggers] = useState(new Map())
useEffect(() => {
if (props.trigger !== "") {
const randomRowName = rows[Math.floor(Math.random() * rows.length)]
setStateTriggers(oldMap => {
const newMap = new Map(oldMap)
newMap.set(randomRowName, Math.random())
return newMap
})
}
l("effect 1")
}, [props.trigger])
const classes = ["typing"]
return <div className={classes.join(" ")}>
{rows.map((rowStyle, rowIndex) => {
let trigger = ""
if (stateTriggers.has(rowStyle)) trigger = stateTriggers.get(rowStyle)
return <TypingIndicatorRow
trigger={trigger}
key={rowIndex}
style={rowStyle}
/>
})}
</div>
}
typingIndicator.propTypes = {
trigger: PropTypes.any,
rows: PropTypes.arrayOf(PropTypes.string),
}
typingIndicator.defaultProps = {
}
export default typingIndicator
$color: #ab7d2e
.typing
.typing-row
height: 8px
.typing-key
display: inline-block
height: 5px
background-color: #ccc
border-radius: 1px
border-top-left-radius: 3px
border-top-right-radius: 3px
transition: all 0.3s
position: relative
top: 0px
&.pressed
background-color: $color
top: 3px
import React, { useEffect, useState } from "react"
import PropTypes from 'prop-types'
const typingIndicatorKey = (props) => {
const [stateIsPressed, setStateIsPressed] = useState(false)
let width = 5
let marginRight = 2
let opacity = 1
let transform = ""
let splitSpacing = 30
const marginLeft = 0
switch (props.style) {
case "p1":
case "p2":
switch (props.index) {
case 0:
case 11:
width = 9
break
case 6:
marginRight = marginRight + 5
width = 0
break
case 5:
marginRight = 5 + splitSpacing
width = 0
break
}
break
case "p3":
switch (props.index) {
case 0:
case 11:
width = 9
break
case 5:
marginRight = splitSpacing
transform = "rotate(30deg) scaleY(2.5) translate(13px, 3px)"
break
case 6:
transform = "rotate(-30deg) scaleY(2.5) translate(-13px, 3px)"
break
}
break
case "p4":
switch (props.index) {
case 0:
case 11:
width = 9
break
case 5:
marginRight = splitSpacing
transform = "rotate(30deg) scaleY(2.5) translate(1px, 0px)"
break
case 6:
transform = "rotate(-30deg) scaleY(2.5) translate(-1px, 0px)"
break
}
break
case "o4":
switch (props.index) {
case 3:
case 4:
width = 5 + 5 + marginRight
}
break
case "s1":
switch (props.index) {
case 9:
width = 12 + marginRight
break
}
break
case "s2":
switch (props.index) {
case 0:
width = 8 + marginRight
break
case 9:
width = 8 + marginRight
break
}
break
case "s3":
switch (props.index) {
case 0:
width = 10 + marginRight
break
case 8:
width = 12 + marginRight
break
}
break
case "s4":
switch (props.index) {
case 0:
width = 7 + marginRight
break
case 3:
width = 5*6 + marginRight
}
break
}
useEffect(() => {
if (props.trigger !== "") {
setStateIsPressed(true)
const timer = window.setTimeout(() => {
setStateIsPressed(false)
}, 200)
return function () {
window.clearTimeout(timer)
}
}
}, [props.trigger])
const classes = ["typing-key"]
if (stateIsPressed) classes.push("pressed")
return <div style={
{
width: width+"px",
marginRight: marginRight+"px",
marginLeft: marginLeft+"px",
opacity: opacity,
transform: transform
}
} className={classes.join(" ")}>
</div>
}
typingIndicatorKey.propTypes = {
trigger: PropTypes.any,
style: PropTypes.string,
index: PropTypes.number,
}
typingIndicatorKey.defaultProps = {
}
export default typingIndicatorKey
import React, { useState, useEffect } from "react"
import PropTypes from 'prop-types'
import TypingIndicatorKey from "./TypingIndicatorKey"
const typingIndicatorRow = (props) => {
const [stateTriggers, setStateTriggers] = useState(new Map())
let keys = 10
switch (props.style) {
case "p1":
case "p2":
case "p3":
case "p4":
keys = 12
break
case "o4":
keys = 8
break
case "s3":
keys = 9
break
case "s4":
keys = 7
break
}
const randomInRange = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
useEffect(() => {
if (props.trigger !== "") {
const offset = randomInRange(0, keys-1)
setStateTriggers(oldMap => {
const newMap = new Map(oldMap)
newMap.set(offset, Math.random())
return newMap
})
}
}, [props.trigger])
const renderKeys = () => {
const returnArray = []
for (let i = 0; i < keys; i++) {
let trigger = ""
if (stateTriggers.has(i)) trigger = stateTriggers.get(i)
returnArray.push(<TypingIndicatorKey
key={i}
index={i}
style={props.style}
trigger={trigger}
/>)
}
return returnArray
}
const classes = ["typing-row"]
return <div className={classes.join(" ")}>
{
renderKeys()
}
</div>
}
typingIndicatorRow.propTypes = {
style: PropTypes.string,
}
typingIndicatorRow.defaultProps = {
}
export default typingIndicatorRow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment