willpower232/TOTPBTF3

View on GitHub
resources/assets/sass/app.scss

Summary

Maintainability
Test Coverage
header img {
    // don't set a max width, just match the line-height of the header
    max-height:2rem;
}

.breadcrumbs {
    // relative positioning helps calculate responsiveness
    display:flex;position:relative;

    &.overflowed {
        justify-content:flex-end;overflow:hidden;

        &:after {
            bottom:0;content:'';left:0;position:absolute;top:0;width:5%;
        }
    }

    a {
        margin:0;text-decoration:none;

        &:before {
            content:'/';margin:0 0.7rem;text-decoration:none;
        }

        &:first-child:before {
            margin-left:0;
        }
    }
}

.folderlist {
    list-style:none;margin-left:-0.5%;padding:0;

    li {
        margin:0.5%;width:99%;
    }

    a {
        align-items:center;display:flex;height:60px;justify-content:center;padding:5px;position:relative;text-decoration:none;
    }

    img {
        display:inline-block;max-height:60px;max-width:100%;
    }

    .replaced-image {
        line-height:60px;
    }
}

label {
    display:block;font-weight:bold;line-height:1em;
}

input:not([type='checkbox']) {
    background:none;box-sizing:border-box;height:3rem;padding:0 1rem;width:100%;

    &.is-invalid {
        //
    }
}

.fieldwrapper {
    position:relative;

    input:first-child {
        margin-top:2em;
    }

    input + label {
        margin:0;position:absolute;top:0.5em;transition:all 0.3s;
    }

    // don't need to test support because invalid selector is skipped right
    // also relies on placeholder attribute on input even if empty
    // see also https://callmenick.com/dev/floated-labels-with-placeholder-shown/
    input:placeholder-shown + label {
        left:1rem;top:3em;
    }
}

.toggle {
    border-radius:10px;cursor:pointer;display:block;height:10px;position:relative;width:40px;

    input {
        display:none;
    }

    .helper {
        border-radius:20px;height:20px;left:-5px;margin:0;position:absolute;top:-5px;transition:all 0.5s;width:20px;
    }

    input:checked + .helper {
        left:calc(100% - 12px);
    }

    input[disabled] + .helper {
        //
    }
}

.invalid-feedback strong {
    //
}

ul {
    padding-left:1em;
}

.buttons {
    justify-self:end;margin-top:auto;
}

form .buttons,.folderlist + .buttons {
    margin-top:2rem;
}

button,.button {
    box-sizing:border-box;cursor:pointer;height:3rem;text-align:center;width:100%;

    &.button-primary {
        //
    }

    &.button-secondary {
        //
    }

    &.button-bad {
        //
    }

    &.button-good {
        //
    }
}

a.button {
    display:block;line-height:3rem;text-decoration:none;
}

dt {
    font-weight:bold;margin-top:2rem;
}

.a-code-header {
    align-items:center;display:flex;flex-direction:row-reverse;justify-content:space-between;

    > * {
        margin:0;
    }

    img {
        max-height:60px;max-width:30%;
    }

    h1 {
        line-height:60px;

        &:only-child {
            flex-grow:1; // fill the space to cancel out the reversed row
        }
    }
}

.text-center {
    text-align:center;
}

.code-and-timer {
    position:relative;
}

.a-code {
    // leave spacing and indenting as ems
    font-family:monospace,monospace;font-size:16vw;letter-spacing:0.2em;text-indent:0.15em;

    @media (min-width:500px) {
        font-size:5rem;
    }
}

.a-timer {
    --progress: 0;

    opacity:0;transition:opacity 0.4s;

    &.show {
        opacity:1;
    }
}

.js-copy {
    opacity:0;transition:all 0.4s;

    &.enabled {
        opacity:1;
    }

    &.success {
        //
    }

    &.failure {
        //
    }
}

.export {
    margin-top:2rem;

    svg {
        display:block;max-width:100%;margin:0 auto;
    }
}