113 lines
3.4 KiB
SCSS
113 lines
3.4 KiB
SCSS
/* =========================================================== *
|
|
* Type Writer Effect *
|
|
/* =========================================================== */
|
|
|
|
/// Replace `$search` with `$replace` in `$string`
|
|
/// @author Kitty Giraudel
|
|
/// @param {String} $string - Initial string
|
|
/// @param {String} $search - Substring to replace
|
|
/// @param {String} $replace ('') - New value
|
|
/// @return {String} - Updated string
|
|
@function str-replace($string, $search, $replace: '') {
|
|
$index: str-index($string, $search);
|
|
|
|
@if $index {
|
|
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
|
|
}
|
|
|
|
@return $string;
|
|
}
|
|
|
|
@function sanitize-int($int) {
|
|
@return str-replace(#{$int}, '.', '_')
|
|
}
|
|
|
|
/* ==================
|
|
* Graphical Container
|
|
*/
|
|
@mixin typing-wrapper($prompt-width, $command-width) {
|
|
.typing-wrapper-#{$prompt-width}-#{$command-width} {
|
|
// wrapper shape + center position
|
|
margin: auto auto;
|
|
width: $prompt-width + $command-width + 1ch; // +1 for cursor width
|
|
|
|
// flexbox alignments
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-content: center;
|
|
align-items: start;
|
|
text-align: start;
|
|
|
|
// XXX: TODO: for some reason this causes an error??
|
|
/* border: 0.5ch solid base.$color-txt; */
|
|
border: 0.5ch solid #ffc0cb;
|
|
padding: 20px;
|
|
}
|
|
}
|
|
|
|
/* ==================
|
|
* TTY Prompt
|
|
*/
|
|
@mixin typing-prompt($prompt-width, $command-width, $typing-duration, $blink-period) {
|
|
// XXX: TODO: relearn SCSS cause the thing below will break whenever an input is given as a float
|
|
// XXX: TODO: (period character interpretted as sub-attribute)
|
|
.typing-prompt-#{$prompt-width}-#{$command-width}-#{$typing-duration}-#{sanitize-int($blink-period)} {
|
|
width: $prompt-width + $command-width; // ignore cursor (right border)
|
|
border-right: 1ch solid; // cursor
|
|
|
|
// hide what the animation hasn't shown yet
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
|
|
// typing animation then start cursor blink
|
|
animation:
|
|
typing($prompt-width) $typing-duration steps($command-width),
|
|
cursor-blink $blink-period steps(1, start) $typing-duration infinite alternate;
|
|
}
|
|
}
|
|
|
|
@mixin typing($prompt-width) {
|
|
@keyframes typing-#{$prompt-width} {
|
|
from {
|
|
width: $prompt-width // ignore effect for prompt
|
|
}
|
|
}
|
|
}
|
|
|
|
@keyframes cursor-blink {
|
|
50% {
|
|
border-color: transparent
|
|
}
|
|
}
|
|
|
|
/* =====================
|
|
* TTY Output
|
|
*/
|
|
@mixin typing-result($typing-duration, $reveal-delay) {
|
|
// XXX: TODO: relearn SCSS cause the thing below will break whenever an input is given as a float
|
|
// XXX: TODO: (period character interpretted as sub-attribute)
|
|
.typing-result-#{$typing-duration}-#{sanitize-int($reveal-delay)} {
|
|
visibility: hidden;
|
|
white-space: pre-wrap; // preserve linebreaks
|
|
|
|
// show result once typing ends + delay
|
|
animation:
|
|
unhide-result 1s ($typing-duration + $reveal-delay) forwards;
|
|
}
|
|
}
|
|
|
|
@keyframes unhide-result {
|
|
to {
|
|
visibility: visible
|
|
}
|
|
}
|
|
|
|
/* =========================
|
|
* Intended Public Interface
|
|
*/
|
|
@mixin tty($prompt-width, $command-width, $typing-duration: 3s, $blink-period: 0.6s, $reveal-delay: 0.8s) {
|
|
@include typing-wrapper($prompt-width, $command-width);
|
|
@include typing-prompt($prompt-width, $command-width, $typing-duration, $blink-period);
|
|
@include typing-result($typing-duration, $reveal-delay);
|
|
}
|