Deduplicate CSS
Sass and webpack don't interact well together. A (non-partial) SCSS file compiled in Sass context and imported from a component will duplicate all its internal imports. Create a single SCSS/CSS stylesheet which is not duplicated multiple times due to per-component import. The fling.scss master style sheet is now imported once in index.js and contains styles for all components. Signed-off-by: Armin Friedl <dev@friedl.net>
This commit is contained in:
parent
eb407f90b6
commit
70cd9c29be
29 changed files with 281 additions and 271 deletions
|
@ -1,8 +1,6 @@
|
|||
import React, {useState} from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import './Error.scss';
|
||||
|
||||
import log from 'loglevel';
|
||||
|
||||
export default (props) => {
|
||||
|
|
|
@ -7,8 +7,6 @@ import FlingContent from './FlingContent';
|
|||
|
||||
import {HashRouter} from 'react-router-dom';
|
||||
|
||||
import './Fling.scss';
|
||||
|
||||
export default function Fling() {
|
||||
const [activeFling, setActiveFling] = useState(undefined);
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ import classNames from 'classnames';
|
|||
|
||||
import {artifactClient} from '../util/flingclient';
|
||||
|
||||
import './FlingArtifacts.scss';
|
||||
|
||||
function FlingArtifactControl(props) {
|
||||
return(
|
||||
<div className={`btn-group ${props.hidden ? "d-invisible": "d-visible"}`}>
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
@import "../styles/base.scss";
|
||||
@import "~spectre.css/src/_variables.scss";
|
||||
|
||||
.table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
thead th {
|
||||
&:nth-child(1) {
|
||||
width:60%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width:20%;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
width:20%;
|
||||
}
|
||||
// control box
|
||||
&:nth-child(4) {
|
||||
text-align: right;
|
||||
width: 4*$control-size;
|
||||
}
|
||||
}
|
||||
|
||||
tbody td {
|
||||
&:nth-child(4) {
|
||||
text-align: right;
|
||||
width: 4*$control-size;
|
||||
}
|
||||
}
|
||||
|
||||
.artifact-row:hover {
|
||||
background-color: $secondary-color;
|
||||
}
|
|
@ -10,8 +10,6 @@ import FlingArtifacts from './FlingArtifacts';
|
|||
import Upload from './Upload';
|
||||
import Settings from './Settings';
|
||||
|
||||
import './FlingContent.scss';
|
||||
|
||||
export default function FlingContent(props) {
|
||||
let location = useLocation();
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
@import "../styles/base.scss";
|
||||
|
||||
.fling-content {
|
||||
@extend %shadow;
|
||||
background-color: #ffffff;
|
||||
}
|
|
@ -5,8 +5,6 @@ import {flingClient} from '../util/flingclient';
|
|||
|
||||
import FlingTile from './FlingTile';
|
||||
|
||||
import './FlingList.scss';
|
||||
|
||||
export default function FlingList(props) {
|
||||
const [flings, setFlings] = useState([]);
|
||||
useEffect(() => { refreshFlingList(); }, [props.activeFling]);
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
@import "../styles/base.scss";
|
||||
@import "~spectre.css/src/_variables.scss";
|
||||
|
||||
.panel {
|
||||
background-color: $light-color;
|
||||
border: none;
|
||||
@extend %shadow;
|
||||
}
|
||||
|
||||
.panel .panel-body {
|
||||
overflow-y: visible;
|
||||
}
|
|
@ -4,8 +4,6 @@ import classNames from 'classnames';
|
|||
|
||||
import {flingClient} from '../util/flingclient';
|
||||
|
||||
import './FlingTile.scss';
|
||||
|
||||
function TileAction(props) {
|
||||
let shareUrlRef = useRef(null);
|
||||
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
@import "../styles/base.scss";
|
||||
@import "~spectre.css/src/_variables.scss";
|
||||
|
||||
.tile.active {
|
||||
background-color: $gray-color-light;
|
||||
}
|
||||
|
||||
.tile:hover {
|
||||
background-color: $secondary-color;
|
||||
}
|
||||
|
||||
.divider {
|
||||
transform: scale(0.8, 1) translate(-10%,0);
|
||||
}
|
||||
|
||||
.input-group-addon.input-group-addon-sm {
|
||||
padding-top: 0.05rem;
|
||||
padding-bottom: 0.05rem;
|
||||
}
|
||||
|
||||
.form-input.input-share-id {
|
||||
cursor: text;
|
||||
box-shadow: none;
|
||||
}
|
|
@ -4,8 +4,6 @@ import {useHistory, useLocation} from 'react-router-dom';
|
|||
|
||||
import request, {setAuth} from '../util/request';
|
||||
|
||||
import './Login.scss';
|
||||
|
||||
import Error from './Error';
|
||||
|
||||
export default () => {
|
||||
|
@ -22,7 +20,7 @@ export default () => {
|
|||
<div className="container-center">
|
||||
<div>
|
||||
<Error errors={errors} clearErrors={clearErrors} >
|
||||
<form className="container-login" onSubmit={handleSubmit}>
|
||||
<form className="login-form" onSubmit={handleSubmit}>
|
||||
<div className="form-group">
|
||||
<label className="form-label" htmlFor="username">Username</label>
|
||||
<input className="form-input" id="username" name="username" type="text" placeholder="Username"
|
||||
|
@ -33,7 +31,7 @@ export default () => {
|
|||
<input className="form-input" id="password" name="password" type="password" placeholder={"*".repeat(18)}
|
||||
value={password} onChange={handleChange} />
|
||||
</div>
|
||||
<div className="form-action-row">
|
||||
<div className="login-action-row">
|
||||
<div className="form-group">
|
||||
<label className="form-switch input-sm">
|
||||
<input type="checkbox" />
|
||||
|
@ -45,7 +43,7 @@ export default () => {
|
|||
</form>
|
||||
</Error>
|
||||
|
||||
<p className="bottom-text">Ready. Set. Fling.</p>
|
||||
<p className="login-footer">Ready. Set. Fling.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
@import "../styles/base.scss";
|
||||
|
||||
.container-login {
|
||||
@extend %shadow;
|
||||
padding: 1rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.bottom-text {
|
||||
text-align: center;
|
||||
font-size: 0.75rem;
|
||||
color: $light-grey;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.form-action-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
|
@ -3,7 +3,6 @@ import React from 'react';
|
|||
|
||||
import request from '../util/request';
|
||||
|
||||
import './Navbar.scss';
|
||||
import send from './send.svg';
|
||||
|
||||
export default function Navbar() {
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
$primary-color: rgb(235, 236, 237);
|
||||
|
||||
@import "../styles/base.scss";
|
||||
@import "~spectre.css/src/_mixins.scss";
|
||||
@import "~spectre.css/src/_variables.scss";
|
||||
@import "~spectre.css/src/_buttons.scss";
|
||||
|
||||
.navbar {
|
||||
@extend %shadow;
|
||||
padding: 0.2rem;
|
||||
background-color: #323334;
|
||||
color: #ebeced;
|
||||
}
|
||||
|
||||
.navbar .navbar-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.1rem;
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.navbar input {
|
||||
background-color: #464748;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.navbar input + button.input-group-btn {
|
||||
background-color: #464748;
|
||||
border: none;
|
||||
border-left: solid;
|
||||
border-left-color: #323334;
|
||||
border-left-width: thin;
|
||||
}
|
||||
|
||||
.navbar-brand img {
|
||||
height: 1.1rem;
|
||||
margin-right: 0.3rem;
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
|
||||
.navbar-control {
|
||||
.btn, a {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
|
@ -5,8 +5,6 @@ import classNames from 'classnames';
|
|||
|
||||
import {flingClient} from '../util/flingclient';
|
||||
|
||||
import './Settings.scss';
|
||||
|
||||
export default function Settings(props) {
|
||||
let [fling, setFling] = useState({name: "", sharing: {directDownload: false, allowUpload: true, shared: true, shareUrl: ""}});
|
||||
let [shareUrlUnique, setShareUrlUnique] = useState(true);
|
||||
|
|
|
@ -7,7 +7,6 @@ import {artifactClient} from '../util/flingclient';
|
|||
|
||||
import upload from './upload.svg';
|
||||
import drop from './drop.svg';
|
||||
import './Upload.scss';
|
||||
|
||||
|
||||
export default function Upload(props) {
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
@import "../styles/base.scss";
|
||||
@import "~spectre.css/src/mixins/_clearfix.scss";
|
||||
@import "~spectre.css/src/mixins/_position.scss";
|
||||
@import "~spectre.css/src/_variables.scss";
|
||||
@import "~spectre.css/src/_layout.scss";
|
||||
@import "~spectre.css/src/utilities/_position.scss";
|
||||
|
||||
.dropzone {
|
||||
@extend %shadow;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dropzone-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.dropzone-icon-upload {
|
||||
@extend .dropzone-icon;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
@extend %shadow;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.file-list .row {
|
||||
@extend .container;
|
||||
@extend .my-2;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.total-upload {
|
||||
float: left;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.btn-upload {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.my-input {
|
||||
inset: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
|
@ -1,30 +1,43 @@
|
|||
%shadow-xs {
|
||||
/***********\
|
||||
| Shadows |
|
||||
\***********/
|
||||
|
||||
@mixin shadow-xs {
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
%shadow-sm {
|
||||
|
||||
@mixin shadow-sm {
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
%shadow {
|
||||
|
||||
@mixin shadow {
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
%shadow-md {
|
||||
|
||||
@mixin shadow-md {
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
%shadow-lg {
|
||||
|
||||
@mixin shadow-lg {
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
%shadow-xl {
|
||||
|
||||
@mixin shadow-xl {
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
%shadow-2xl {
|
||||
|
||||
@mixin shadow-2xl {
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
%shadow-inner {
|
||||
|
||||
@mixin shadow-inner {
|
||||
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
%shadow-outline {
|
||||
|
||||
@mixin shadow-outline {
|
||||
box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
|
||||
}
|
||||
%shadow-none {
|
||||
|
||||
@mixin shadow-none {
|
||||
box-shadow: none;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* Center within viewport */
|
||||
// A flex container that centers it's children within the viewport
|
||||
.container-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
37
web/fling/src/style/_variables.scss
Normal file
37
web/fling/src/style/_variables.scss
Normal file
|
@ -0,0 +1,37 @@
|
|||
/**********\
|
||||
| Colors |
|
||||
\**********/
|
||||
// Primary colors
|
||||
$blue-grey: #718096;
|
||||
$grey: #cbd5e0;
|
||||
$light-grey: #ebeced;
|
||||
$dark-grey: #464748;
|
||||
$red: #e53e3e;
|
||||
$black: #323334;
|
||||
|
||||
// Semantic colors
|
||||
$primary-color: #4693d2;
|
||||
$canvas-base-color: $grey;
|
||||
$navbar-base-color: $black;
|
||||
$navbar-color: $light-grey;
|
||||
|
||||
/*********\
|
||||
| Fonts |
|
||||
\*********/
|
||||
|
||||
// Sizes
|
||||
$font-size-base: 1rem; // Assumes the browser default, typically `16px`
|
||||
$font-size-lg: $font-size-base * 1.25;
|
||||
$font-size-sm: $font-size-base * .875;
|
||||
$font-size-xs: $font-size-base * .75;
|
||||
|
||||
|
||||
|
||||
/**************\
|
||||
| Breakpoints |
|
||||
\**************/
|
||||
|
||||
$sm: '640px';
|
||||
$md: '768px';
|
||||
$lg: '1024px';
|
||||
$xl: '1280px';
|
217
web/fling/src/style/fling.scss
Normal file
217
web/fling/src/style/fling.scss
Normal file
|
@ -0,0 +1,217 @@
|
|||
@import "variables";
|
||||
@import "mixins";
|
||||
@import "utils";
|
||||
|
||||
@import "~spectre.css/src/spectre.scss";
|
||||
@import "~spectre.css/src/spectre-icons.scss";
|
||||
@import "~spectre.css/src/spectre-exp.scss";
|
||||
|
||||
|
||||
body {
|
||||
background-color: $canvas-base-color;
|
||||
}
|
||||
|
||||
/*********\
|
||||
| Login |
|
||||
\*********/
|
||||
|
||||
// Basic styling for the login form
|
||||
.login-form {
|
||||
@include shadow;
|
||||
padding: 1rem;
|
||||
border-radius: 0.25rem;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
// Row of actions - submit, remember me
|
||||
.login-action-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
// Little grey text at the bottom of the login box
|
||||
.login-footer {
|
||||
text-align: center;
|
||||
font-size: 0.75rem;
|
||||
color: $light-grey;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
/*********\
|
||||
| Navbar |
|
||||
\*********/
|
||||
|
||||
.navbar {
|
||||
@include shadow;
|
||||
padding: 0.4rem;
|
||||
background-color: $navbar-base-color;
|
||||
color: $navbar-color;
|
||||
|
||||
.navbar-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.1rem;
|
||||
color: $navbar-color;
|
||||
|
||||
img {
|
||||
height: 1.1rem;
|
||||
margin-right: 0.3rem;
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
background-color: $dark-grey;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn.btn-link {
|
||||
color: $navbar-color;
|
||||
}
|
||||
|
||||
input + button.input-group-btn {
|
||||
background-color: $dark-grey;
|
||||
border: none;
|
||||
border-left: solid;
|
||||
border-left-color: $navbar-base-color;
|
||||
border-left-width: thin;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-control {
|
||||
.btn, a {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
||||
|
||||
/*************\
|
||||
| FlingList |
|
||||
\*************/
|
||||
.panel {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/*************\
|
||||
| FlingTile |
|
||||
\*************/
|
||||
|
||||
.divider {
|
||||
transform: scale(0.8, 1) translate(-10%,0);
|
||||
}
|
||||
|
||||
.tile{
|
||||
&.active {
|
||||
background-color: $gray-color-light;
|
||||
}
|
||||
&:hover {
|
||||
background-color: $secondary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon.input-group-addon-sm {
|
||||
padding-top: 0.05rem;
|
||||
padding-bottom: 0.05rem;
|
||||
}
|
||||
|
||||
.form-input.input-share-id {
|
||||
cursor: text;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/****************\
|
||||
| FlingContent |
|
||||
\****************/
|
||||
|
||||
.fling-content {
|
||||
@include shadow;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/******************\
|
||||
| FlingArtifacts |
|
||||
\******************/
|
||||
|
||||
.table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
thead th {
|
||||
&:nth-child(1) {
|
||||
width:60%;
|
||||
}
|
||||
&:nth-child(2) {
|
||||
width:20%;
|
||||
}
|
||||
&:nth-child(3) {
|
||||
width:20%;
|
||||
}
|
||||
// control box
|
||||
&:nth-child(4) {
|
||||
text-align: right;
|
||||
width: 4*$control-size;
|
||||
}
|
||||
}
|
||||
|
||||
tbody td {
|
||||
&:nth-child(4) {
|
||||
text-align: right;
|
||||
width: 4*$control-size;
|
||||
}
|
||||
}
|
||||
|
||||
.artifact-row:hover {
|
||||
background-color: $secondary-color;
|
||||
}
|
||||
|
||||
/**********\
|
||||
| Upload |
|
||||
\**********/
|
||||
|
||||
.dropzone {
|
||||
@include shadow;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dropzone-icon {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.dropzone-icon-upload {
|
||||
@extend .dropzone-icon;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
@include shadow;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.file-list .row {
|
||||
@extend .container;
|
||||
@extend .my-2;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.total-upload {
|
||||
float: left;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.btn-upload {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.my-input {
|
||||
inset: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
@import "~normalize.css/normalize.css";
|
||||
|
||||
@import "~spectre.css/dist/spectre.min.css";
|
||||
@import "~spectre.css/dist/spectre-icons.css";
|
||||
|
||||
@import "partials/_shadows.scss";
|
||||
@import "variables/_breakpoints.scss";
|
||||
@import "variables/_colors.scss";
|
||||
|
||||
@import "form.scss";
|
||||
@import "container.scss";
|
||||
|
||||
body {
|
||||
background-color: #ebeced;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
@import "variables/_colors.scss";
|
||||
@import "variables/_sizes.scss";
|
||||
@import "partials/_shadows.scss";
|
||||
|
||||
.form-input {
|
||||
@extend %shadow;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.form-input-error {
|
||||
border-color: $red;
|
||||
}
|
||||
|
||||
.form-error-text {
|
||||
color: $red;
|
||||
font-size: $font-size-xs;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
$sm: '640px';
|
||||
$md: '768px';
|
||||
$lg: '1024px';
|
||||
$xl: '1280px';
|
|
@ -1,4 +0,0 @@
|
|||
$grey: #718096;
|
||||
$light-grey: #cbd5e0;
|
||||
|
||||
$red: #e53e3e;
|
|
@ -1,4 +0,0 @@
|
|||
$font-size-base: 1rem; // Assumes the browser default, typically `16px`
|
||||
$font-size-lg: $font-size-base * 1.25;
|
||||
$font-size-sm: $font-size-base * .875;
|
||||
$font-size-xs: $font-size-base * .75;
|
Loading…
Reference in a new issue