A Pen by Mustafa Enes on CodePen.
Created
February 26, 2017 21:05
-
-
Save scriptype/95cb8b0afcc693df703ef26dbd61d489 to your computer and use it in GitHub Desktop.
MpYKVq
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="game"> | |
<h1 class="game__title">Satisfy the inputs</h1> | |
<div class="game__screen" id="game-screen"></div> | |
<div class="game__hud"> | |
<div class="game__lives" id="game-lives"></div> | |
<div class="game__score" id="game-score"></div> | |
</div> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define('$.markupToDOM', _ => markup => { | |
var parent = document.createElement('div') | |
return (function() { | |
parent.innerHTML = markup.trim() | |
return parent.removeChild(parent.firstChild) | |
})() | |
}) | |
define('State', _ => (data, onChange) => Object.assign(data, { | |
update(newState) { | |
Object.assign(this, newState) | |
onChange(newState) | |
} | |
})) | |
define('$', ['$.markupToDOM'], markupToDOM => selector => { | |
var bareSelector = selector.trim() | |
var firstChar = bareSelector.charAt(0) | |
if (firstChar == '#') { | |
return document.getElementById(selector.slice(1)) | |
} else if (firstChar == '<') { | |
return markupToDOM(bareSelector) | |
} | |
return document.querySelectorAll(selector) | |
}) | |
define('Game.Globals.SeedNoise', _ => _ => { | |
noise.seed(Math.random()) | |
}) | |
define('Game.Objects.Text', ['$'], $ => _ => ({ | |
CLASS_NAME: 'text-object', | |
template(whatToType, question) { | |
return $(` | |
<label class="${ this.CLASS_NAME }"> | |
<span class="${ this.CLASS_NAME }__title"> | |
${ question ? 'question: ' : 'type: '} | |
${ question || whatToType } | |
</span> | |
<input | |
type="text" | |
class="${ this.CLASS_NAME }__input" /> | |
</label> | |
`) | |
}, | |
create({ question, whatToType, satisfactionCB }) { | |
this.state = { | |
isValid: true | |
} | |
this.$el = this.template(whatToType, question) | |
this.question = question | |
this.whatToType = whatToType | |
this.satisfactionCB = satisfactionCB | |
return this | |
}, | |
render($container) { | |
$container.appendChild(this.$el) | |
this.$el.addEventListener('input', e => this.onInput(e)) | |
return this | |
}, | |
destroy() { | |
this.$el.remove() | |
return this | |
}, | |
onInput(event) { | |
var value = event.target.value | |
if (value === this.whatToType) { | |
this.satisfactionCB.call(this) | |
} else { | |
this.validate(value) | |
} | |
}, | |
validate(value) { | |
var wasValid = this.state.isValid | |
var isValid = this.whatToType.includes(value) | |
// If validity changed since last time | |
// XOR: True only if the values are different | |
if (wasValid ^ isValid) { | |
this.$el.classList.toggle(this.CLASS_NAME + '--invalid') | |
this.state.isValid = !wasValid | |
} | |
} | |
})) | |
define('Game.Atoms.Button', ['$'], $ => _ => ({ | |
CLASS_NAME: 'button-object', | |
template(buttonText) { | |
return $(` | |
<button | |
type="button" | |
class="${ this.CLASS_NAME }"> | |
${ buttonText } | |
</button> | |
`) | |
}, | |
create({ buttonText='Click me', onClickCB }) { | |
this.$el = this.template(buttonText) | |
this.buttonText = buttonText | |
this.onClickCB = onClickCB | |
return this | |
}, | |
render($container) { | |
$container.appendChild(this.$el) | |
this.$el.addEventListener('click', e => this.onClick(e)) | |
return this | |
}, | |
destroy() { | |
this.$el.remove() | |
return this | |
}, | |
onClick() { | |
this.onClickCB.call(this) | |
} | |
})) | |
define('Game.Objects.Button', ['Game.Atoms.Button'], ButtonAtom => _ => ({ | |
create(options) { | |
return ButtonAtom().create(Object.assign({}, options, { | |
onClickCB: options.satisfactionCB | |
})) | |
} | |
})) | |
define('Game.Atoms.Checkbox', ['$'], $ => _ => ({ | |
CLASS_NAME: 'checkbox-object', | |
template(label, isGrouped) { | |
var mod = isGrouped ? this.CLASS_NAME + '--grouped' : '' | |
return $(` | |
<label class="${ this.CLASS_NAME } ${ mod }"> | |
<input | |
type="checkbox" | |
class="${ this.CLASS_NAME }__check" /> | |
${ !label ? '' : ` | |
<span class="${ this.CLASS_NAME }__title"> | |
${ label } | |
</span> | |
` } | |
</label> | |
`) | |
}, | |
create({ | |
isChecked = false, | |
label, | |
isGrouped, | |
onChangeCB | |
}) { | |
this.$el = this.template(label, isGrouped) | |
this.isChecked = isChecked | |
this.onChangeCB = onChangeCB | |
return this | |
}, | |
render($container) { | |
$container.appendChild(this.$el) | |
if (this.isChecked) { | |
this.$el.querySelector('input').checked = true | |
} | |
this.$el.addEventListener('change', e => this.onChange(e)) | |
return this | |
}, | |
destroy() { | |
this.$el.remove() | |
return this | |
}, | |
onChange(e) { | |
this.onChangeCB.call(this, e.target.checked) | |
} | |
})) | |
define('Game.Objects.Checkbox', ['Game.Atoms.Checkbox'], CheckboxAtom => _ => ({ | |
create(options) { | |
return CheckboxAtom().create(Object.assign({}, options, { | |
onChangeCB: options.satisfactionCB | |
})) | |
} | |
})) | |
define('Game.Atoms.Radio', ['$'], $ => _ => ({ | |
CLASS_NAME: 'radio-object', | |
template(name, isGrouped, label) { | |
var mod = isGrouped ? this.CLASS_NAME + '--grouped' : '' | |
return $(` | |
<label class="${ this.CLASS_NAME } ${ mod }"> | |
<input | |
name="${ name }" | |
type="radio" | |
class="${ this.CLASS_NAME }__check" /> | |
${ !label ? '' : ` | |
<span class="${ this.CLASS_NAME }__title"> | |
${ label } | |
</span> | |
` } | |
</label> | |
`) | |
}, | |
create({ name, isGrouped, label, onChangeCB }) { | |
this.$el = this.template(name, isGrouped, label) | |
this.onChangeCB = onChangeCB | |
return this | |
}, | |
render($container) { | |
$container.appendChild(this.$el) | |
this.$el.addEventListener('change', e => this.onChange(e)) | |
return this | |
}, | |
destroy() { | |
this.$el.remove() | |
return this | |
}, | |
onChange(e) { | |
this.onChangeCB.call(this, e.target.checked) | |
} | |
})) | |
define('Game.Objects.Radio', ['Game.Atoms.Radio'], RadioAtom => _ => ({ | |
create(options) { | |
return RadioAtom().create(Object.assign({}, options, { | |
onChangeCB: options.satisfactionCB | |
})) | |
} | |
})) | |
define('Game.Objects.RadioQuestion', [ | |
'$', | |
'Game.Atoms.Radio', | |
'Game.Atoms.Button' | |
], ( | |
$, | |
RadioAtom, | |
ButtonAtom | |
) => _ => ({ | |
CLASS_NAME: 'radio-question-object', | |
template(label) { | |
return $(` | |
<form class="${ this.CLASS_NAME }"> | |
<span class="${ this.CLASS_NAME }__title"> | |
${ label } | |
</span> | |
<div | |
data-options | |
class="${ this.CLASS_NAME }__options"> | |
</div> | |
</form> | |
`) | |
}, | |
create({ data, withButton, satisfactionCB }) { | |
this.UID = 'rq-' + Date.now() | |
this.state = { | |
selected: null | |
} | |
this.$el = this.template(data.question) | |
this.data = data | |
this.withButton = withButton | |
this.satisfactionCB = satisfactionCB | |
return this | |
}, | |
render($container) { | |
$container.appendChild(this.$el) | |
var self = this | |
this.data.options.forEach((option, index) => { | |
RadioAtom() | |
.create({ | |
name: this.UID, | |
isGrouped: true, | |
label: option, | |
onChangeCB(isChecked) { | |
if (self.withButton) { | |
self.state.selected = index | |
} else if (self.data.answer === index) { | |
self.satisfactionCB.call(self) | |
} | |
} | |
}) | |
.render(this.$el.querySelector('[data-options]')) | |
}) | |
if (this.withButton) { | |
ButtonAtom() | |
.create({ | |
onClickCB() { | |
if (self.state.selected === self.data.answer) { | |
self.satisfactionCB.call(self) | |
} | |
} | |
}) | |
.render(this.$el) | |
} | |
return this | |
}, | |
destroy() { | |
this.$el.remove() | |
return this | |
} | |
})) | |
define('Game.Objects.CheckboxQuestion', [ | |
'$', | |
'Game.Atoms.Checkbox', | |
'Game.Atoms.Button' | |
], ( | |
$, | |
CheckboxAtom, | |
ButtonAtom | |
) => _ => ({ | |
CLASS_NAME: 'checkbox-question-object', | |
template(label) { | |
return $(` | |
<form class="${ this.CLASS_NAME }"> | |
<span class="${ this.CLASS_NAME }__title"> | |
${ label } | |
</span> | |
<div | |
data-options | |
class="${ this.CLASS_NAME }__options"> | |
</div> | |
</form> | |
`) | |
}, | |
create({ data, withButton, satisfactionCB }) { | |
this.UID = 'cq-' + Date.now() | |
this.state = { | |
options: data.options.map(o => 0) | |
} | |
this.$el = this.template(data.question) | |
this.data = data | |
this.withButton = withButton | |
this.satisfactionCB = satisfactionCB | |
return this | |
}, | |
render($container) { | |
$container.appendChild(this.$el) | |
var self = this | |
this.data.options.forEach((option, index) => { | |
CheckboxAtom() | |
.create({ | |
isGrouped: true, | |
label: option, | |
onChangeCB(isChecked) { | |
self.state.options[index] = +isChecked | |
if (!self.withButton) { | |
var flag = self.state.options.join('') | |
if (flag === self.data.answer) { | |
self.satisfactionCB.call(self) | |
} | |
} | |
} | |
}) | |
.render(this.$el.querySelector('[data-options]')) | |
}) | |
if (this.withButton) { | |
ButtonAtom() | |
.create({ | |
onClickCB() { | |
var flag = self.state.options.join('') | |
if (flag === self.data.answer) { | |
self.satisfactionCB.call(self) | |
} | |
} | |
}) | |
.render(this.$el) | |
} | |
return this | |
}, | |
destroy() { | |
this.$el.remove() | |
return this | |
} | |
})) | |
define('Game.Objects.FallingLayer', ['$'], $ => _ => ({ | |
CLASS_NAME: 'falling-layer-object', | |
template() { | |
return $(` | |
<div class="${ this.CLASS_NAME }"></div> | |
`) | |
}, | |
create({ speed = 5, onEnd }) { | |
this.speed = speed | |
this.onEnd = onEnd | |
return this | |
}, | |
render($parent) { | |
this.destroyed = false | |
this.noiseX = Math.random() | |
this.$el = this.template() | |
$parent.appendChild(this.$el) | |
requestAnimationFrame(_ => { | |
var s = this.getInitialSizes($parent) | |
var top = -s.height | |
var left = Math.random() * (s.parentWidth - s.width) | |
this.$el.style.cssText += `; | |
top: ${ top }px; | |
left: ${ left }px; | |
` | |
this.fall(Object.assign({}, s, { top, left })) | |
}) | |
return this | |
}, | |
destroy() { | |
this.$el.remove() | |
this.destroyed = true | |
return this | |
}, | |
getInitialSizes($parent) { | |
return { | |
top: this.$el.offsetTop, | |
left: this.$el.offsetLeft, | |
width: this.$el.offsetWidth, | |
height: this.$el.offsetHeight, | |
parentWidth: $parent.offsetWidth, | |
parentHeight: $parent.offsetHeight | |
} | |
}, | |
fall({ | |
top, | |
left, | |
width, | |
height, | |
parentWidth, | |
parentHeight | |
}) { | |
requestAnimationFrame(_ => { | |
if (this.destroyed) { | |
return false | |
} | |
var incTop = 0 | |
if (top + height < parentHeight) { | |
incTop = this.speed / 10 | |
} | |
var incLeft = noise.simplex2( | |
this.noiseX / parentHeight, | |
top / parentHeight * this.speed | |
) * this.speed / 5 | |
if ( | |
left <= 0 && incLeft < 0 || | |
left + width + incLeft >= parentWidth | |
) { | |
incLeft *= -1 | |
} | |
if (incTop > 0) { | |
var newTop = top + incTop | |
var newLeft = left + incLeft | |
this.$el.style.cssText += `; | |
top: ${ newTop }px; | |
left: ${ newLeft }px; | |
` | |
this.fall({ | |
top: newTop, | |
left: newLeft, | |
width, | |
height, | |
parentWidth, | |
parentHeight | |
}) | |
} else { | |
this.onEnd() | |
} | |
}) | |
} | |
})) | |
define('Game.Vocabulary.Texts', [ | |
'hello', | |
'world' | |
]) | |
define('Game.Vocabulary.CheckboxTitles', [ | |
'Check this', | |
'Check', | |
'' | |
]) | |
define('Game.Vocabulary.NegativeCheckboxTitles', [ | |
'Uncheck this', | |
'Uncheck', | |
'' | |
]) | |
define('Game.Vocabulary.RadioTitles', [ | |
'Select this', | |
'Select', | |
'' | |
]) | |
define('Game.Vocabulary.ButtonTitles', [ | |
'Click me', | |
'Click this', | |
'Click!' | |
]) | |
define('Game.Vocabulary.TextQuestions', [{ | |
question: 'The opposite of "yes"', | |
answer: 'no' | |
}, { | |
question: '2 + 2 = ?', | |
answer: '4' | |
}]) | |
define('Game.Vocabulary.RadioQuestions', [{ | |
question: 'Here is a question', | |
answer: 2, | |
options: [ | |
'Really?', | |
'Oh, thanks!', | |
'No, it\'s not.', | |
'Sweet.' | |
] | |
}, { | |
question: 'Which is a fruit?', | |
answer: 1, | |
options: [ | |
'A door', | |
'A banana', | |
'A computer', | |
'A cat' | |
] | |
}]) | |
define('Game.Vocabulary.CheckboxQuestions', [{ | |
question: 'A banana is', | |
answer: '0110', | |
options: [ | |
'A vehicle', | |
'A fruit', | |
'Yellow or green', | |
'A person' | |
] | |
}, { | |
question: 'Which are correct?', | |
answer: '101', | |
options: [ | |
'2^6 = 64', | |
'15 - 4 = 19', | |
'2 * 2 = 4' | |
] | |
}]) | |
define('Game.Level', [ | |
'Game.Vocabulary.Texts', | |
'Game.Vocabulary.CheckboxTitles', | |
'Game.Vocabulary.NegativeCheckboxTitles', | |
'Game.Vocabulary.RadioTitles', | |
'Game.Vocabulary.ButtonTitles', | |
'Game.Vocabulary.TextQuestions', | |
'Game.Vocabulary.RadioQuestions', | |
'Game.Vocabulary.CheckboxQuestions', | |
'Game.Objects.FallingLayer', | |
'Game.Objects.Text', | |
'Game.Objects.Checkbox', | |
'Game.Objects.Radio', | |
'Game.Objects.Button', | |
'Game.Objects.RadioQuestion', | |
'Game.Objects.CheckboxQuestion' | |
], ( | |
VocTexts, | |
VocCheckboxTitles, | |
VocNegativeCheckboxTitles, | |
VocRadioTitles, | |
VocButtonTitles, | |
VocTextQuestions, | |
VocRadioQuestions, | |
VocCheckboxQuestions, | |
FallingLayerObject, | |
TextObject, | |
CheckboxObject, | |
RadioObject, | |
ButtonObject, | |
RadioQuestionObject, | |
CheckboxQuestionObject | |
) => _ => ({ | |
setup({ | |
$screen, | |
totalLevelCount, | |
difficulty, | |
onScore, | |
onDie, | |
onComplete | |
}) { | |
this.$screen = $screen | |
this.totalLevelCount = totalLevelCount | |
this.difficulty = difficulty | |
this.onScore = onScore | |
this.onDie = onDie | |
this.onComplete = onComplete | |
var _log2 = Math.log2(difficulty + 1) | |
this.objectCount = difficulty * 4 | |
this.satisfiedCount = 0 | |
this.launchedCount = 0 | |
this.pointsPerObject = (250 * _log2) / this.objectCount | |
this.waitBeforeNextObject = 5000 / difficulty | |
this.noPointsAfter = 10000 / _log2 | |
this.fullPointsBefore = 4000 / _log2 | |
this.fallSpeed = 2 + _log2 | |
this.ObjectTypes = { | |
Text: 0, | |
Checkbox: 1, | |
NegativeCheckbox: 2, | |
Radio: 3, | |
Button: 4, | |
TextQuestion: 5, | |
CheckboxQuestion: 6, | |
RadioQuestion: 7 | |
} | |
return this | |
}, | |
_getRandom(source) { | |
var slice | |
if (source.length < this.totalLevelCount) { | |
slice = source | |
} else { | |
var chunk = Math.max(Math.floor(source.length / this.totalLevelCount), 1) | |
var lowerBound = chunk * (this.difficulty - 1) | |
var upperBound = chunk * this.difficulty | |
slice = source.slice(lowerBound, upperBound) | |
} | |
return slice[Math.floor(Math.random() * slice.length)] | |
}, | |
launchNewObject() { | |
var objectTypeCount = Object.keys(this.ObjectTypes).length | |
var RandomObject | |
var objectOptions | |
switch (Math.floor(Math.random() * objectTypeCount)) { | |
case this.ObjectTypes.Text: | |
RandomObject = TextObject | |
objectOptions = { | |
whatToType: this._getRandom(VocTexts) | |
} | |
break | |
case this.ObjectTypes.Checkbox: | |
RandomObject = CheckboxObject | |
objectOptions = { | |
label: this._getRandom(VocCheckboxTitles) | |
} | |
break | |
case this.ObjectTypes.NegativeCheckbox: | |
RandomObject = CheckboxObject | |
objectOptions = { | |
isNegative: true, | |
isChecked: true, | |
label: this._getRandom(VocNegativeCheckboxTitles) | |
} | |
break | |
case this.ObjectTypes.Radio: | |
RandomObject = RadioObject | |
objectOptions = { | |
label: this._getRandom(VocRadioTitles) | |
} | |
break | |
case this.ObjectTypes.Button: | |
RandomObject = ButtonObject | |
objectOptions = { | |
label: this._getRandom(VocButtonTitles) | |
} | |
break | |
case this.ObjectTypes.TextQuestion: | |
RandomObject = TextObject | |
var data = this._getRandom(VocTextQuestions) | |
objectOptions = { | |
whatToType: data.answer, | |
question: data.question | |
} | |
break | |
case this.ObjectTypes.CheckboxQuestion: | |
RandomObject = CheckboxQuestionObject | |
objectOptions = { | |
data: this._getRandom(VocCheckboxQuestions) | |
} | |
break | |
case this.ObjectTypes.RadioQuestion: | |
RandomObject = RadioQuestionObject | |
objectOptions = { | |
data: this._getRandom(VocRadioQuestions) | |
} | |
break | |
} | |
var launchTime = Date.now() | |
var $fallingLayer = FallingLayerObject() | |
.create({ | |
speed: this.fallSpeed, | |
onEnd: _ => this.onDie() | |
}) | |
.render(this.$screen) | |
var self = this | |
RandomObject() | |
.create(Object.assign({}, objectOptions, { | |
satisfactionCB() { | |
this.destroy() | |
$fallingLayer.destroy() | |
var startTime = launchTime + self.fullPointsBefore | |
var diff = Math.max(Date.now() - startTime, 0) | |
var ratio = Math.max(self.noPointsAfter / diff, 1) | |
var divider = Math.sin((Math.PI / 2) / ratio) | |
var score = self.pointsPerObject * (1 - divider) | |
console.log(diff, score) | |
self.onScore(score) | |
if (++self.satisfiedCount === self.objectCount) { | |
self.onComplete() | |
} | |
} | |
})) | |
.render($fallingLayer.$el) | |
if (++this.launchedCount < this.objectCount) { | |
setTimeout( | |
this.launchNewObject.bind(this), | |
this.waitBeforeNextObject | |
) | |
} | |
}, | |
start() { | |
this.launchNewObject() | |
} | |
})) | |
define('Game', [ | |
'$', | |
'State', | |
'Game.Globals.SeedNoise', | |
'Game.Level' | |
], ( | |
$, | |
State, | |
SeedNoise, | |
Level | |
) => { | |
SeedNoise() | |
var state = State({ | |
score: 0, | |
level: 1, | |
lives: 3 | |
}, changed => { | |
renderHUD() | |
}) | |
var $screen = $('#game-screen') | |
var $lives = $('#game-lives') | |
var $score = $('#game-score') | |
function renderHUD() { | |
$lives.innerHTML = new Array(state.lives + 1).join(` | |
<span class="game__lives-heart">♥︎</span> | |
`) | |
$score.innerText = `Score: ${ parseInt(state.score, 10) }` | |
} | |
function startLevel(lvl) { | |
var $levelTitle = $(`<h2>Level ${ lvl + 1 }</h2>`) | |
$screen.appendChild($levelTitle) | |
setTimeout(_ => { | |
$levelTitle.remove() | |
levels[lvl].start() | |
}, 1500) | |
} | |
function endGame() { | |
$screen.appendChild($(`<h1>The end.</h1>`)) | |
} | |
function startGame() { | |
startLevel(0) | |
renderHUD() | |
} | |
startGame() | |
var levelCount = 10 | |
var levels = new Array(levelCount) | |
.join(' ') | |
.split(' ') | |
.map((e, lvl) => Level().setup({ | |
$screen, | |
totalLevelCount: levelCount, | |
difficulty: lvl + 1, | |
onScore(score) { | |
state.update({ | |
score: state.score + score | |
}) | |
}, | |
onDie() { | |
state.update({ | |
lives: state.lives - 1 | |
}) | |
}, | |
onComplete() { | |
state.update({ | |
level: state.level + 1 | |
}) | |
setTimeout(_ => { | |
if (lvl + 1 < levels.length) { | |
startLevel(lvl + 1) | |
} else { | |
endGame() | |
} | |
}, 1500) | |
} | |
})) | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="http://codepen.io/pavlovsk/pen/bBqeBB"></script> | |
<script src="https://cdn.rawgit.com/josephg/noisejs/master/perlin.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* { | |
box-sizing: border-box; | |
} | |
html, body { | |
height: 100%; | |
} | |
body { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
margin: 0; | |
font: 100 normal 16px/1.5 helvetica, sans-serif; | |
background: #ddd; | |
color: #1d1d1d; | |
} | |
.game { | |
display: flex; | |
flex-direction: column; | |
justify-content: space-between; | |
width: 500px; | |
height: 90%; | |
max-height: 720px; | |
padding: 0 1.5em; | |
background: #fff; | |
border-radius: 3px; | |
box-shadow: 1px 1px 5px rgba(0, 0, 0, .1); | |
&__title { | |
text-align: center; | |
margin: 0; | |
padding: .5em; | |
} | |
&__screen { | |
position: relative; | |
height: 100%; | |
overflow: hidden; | |
background: #f0f0f0; | |
box-shadow: inset 2px 2px 10px rgba(0, 0, 0, .1); | |
} | |
&__hud { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
height: 80px; | |
} | |
&__lives-heart { | |
color: red; | |
font-size: 1.5em; | |
} | |
&__score { | |
font-family: 'Libre Baskerville', serif; | |
} | |
} | |
.text-object, | |
.checkbox-object:not(.checkbox-object--grouped), | |
.radio-object:not(.radio-object--grouped), | |
.button-object, | |
.radio-question-object, | |
.checkbox-question-object { | |
padding: .5em; | |
font-size: .8em; | |
border-radius: 3px; | |
} | |
.text-object { | |
display: inline-block; | |
width: 120px; | |
background: #3C3B5C; | |
color: #fff; | |
border-bottom: 1px solid hsla(240, 42%, 20%, 1); | |
&__title { | |
display: block; | |
text-align: center; | |
} | |
&__input { | |
width: 100%; | |
padding: .25em; | |
font-size: 15px; | |
border: 1px solid #ccc; | |
border-radius: 1px; | |
transition: all .3s; | |
} | |
&--invalid &__input { | |
border: 1px solid #f55; | |
outline-color: #f55; | |
} | |
} | |
.checkbox-object, | |
.radio-object { | |
display: inline-block; | |
&__check { | |
margin: 0; | |
} | |
} | |
.checkbox-object:not(.checkbox-object--grouped) { | |
background: #FFB563; | |
border-bottom: 1px solid hsla(30, 100%, 56%, 1); | |
} | |
.radio-object:not(.radio-object--grouped) { | |
background: #7B3C59; | |
color: #fff; | |
border-bottom: 1px solid hsla(337, 50%, 20%, 1); | |
} | |
.radio-question-object, | |
.checkbox-question-object { | |
display: inline-block; | |
&__title { | |
display: inline-block; | |
padding: 0 .25em; | |
} | |
} | |
.radio-question-object { | |
color: #fff; | |
background: #7B3C59; | |
border-bottom: 1px solid hsla(337, 50%, 20%, 1); | |
.radio-object--grouped { | |
display: block; | |
} | |
} | |
.checkbox-question-object { | |
background: #FFB563; | |
border-bottom: 1px solid hsla(30, 100%, 56%, 1); | |
.checkbox-object--grouped { | |
display: block; | |
} | |
} | |
.button-object { | |
background: #D53939; | |
color: #fff; | |
border: none; | |
border-bottom: 1px solid hsla(0, 80%, 25%, 1); | |
line-height: 1.5 | |
} | |
.falling-layer-object { | |
display: inline-block; | |
position: absolute; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<link href="https://fonts.googleapis.com/css?family=Libre+Baskerville:700" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment