initial bootstrap/navbar setup akin to bones73k implementation

This commit is contained in:
Adam Piontek 2021-03-29 11:27:44 -04:00
parent dfe805b811
commit 0a83f8f317
32 changed files with 6856 additions and 7865 deletions

View file

@ -0,0 +1,35 @@
// Colors
// $primary: #662c91;
// $secondary: #ee6c4d;
// $success: #3f784c;
// $info: #3f84e5;
// $warning: #ffec51;
$light: $gray-200;
$dark: $gray-800;
// Create your own map
$custom-colors: (
"primary": $primary,
"secondary": $secondary,
"success": $success,
"info": $info,
"warning": $warning,
"danger": $danger,
"light": $light,
"dark": $dark,
"gray": $gray-500,
);
// $custom-colors: (
// "custom-color": #900
// );
// Merge the maps
$theme-colors: map-merge($theme-colors, $custom-colors);
// misc
$navbar-dark-color: rgba($white, 0.75);
$navbar-dark-hover-color: rgba($white, 0.9);
$navbar-dark-active-color: $white;
$navbar-dark-disabled-color: rgba($white, 0.45);
$navbar-dark-toggler-border-color: rgba($white, 0.3);

View file

@ -0,0 +1,21 @@
/* Bootstrap custom variable overrides */
// Typography
//
// Font, line-height, and color for body text, headings, and more.
// stylelint-disable value-keyword-case
$font-family-sans-serif: Lato, system-ui, -apple-system, "Segoe UI", Roboto,
"Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !important;
$font-family-secondary: Righteous, system-ui, -apple-system, "Segoe UI", Roboto,
"Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !important;
$font-family-monospace: "Fira Mono", SFMono-Regular, Menlo, Monaco, Consolas,
"Liberation Mono", "Courier New", monospace !important;
$font-family-code: "Fira Code", "Fira Mono", SFMono-Regular, Menlo, Monaco,
Consolas, "Liberation Mono", "Courier New", monospace !important;
// Features
$enable-shadows: true;
$enable-negative-margins: true;

50
assets/css/_bs-load.scss Normal file
View file

@ -0,0 +1,50 @@
/* Bootstrap custom variable overrides */
@import "bs-custom";
// Required || Configuration
@import "../node_modules/bootstrap/scss/functions";
@import "../node_modules/bootstrap/scss/variables";
/* Bootstrap custom variable overrides */
@import "bs-colors";
// Required || Configuration -- CONTINUED
@import "../node_modules/bootstrap/scss/mixins";
@import "../node_modules/bootstrap/scss/utilities";
// Optional || Layout & components
@import "../node_modules/bootstrap/scss/root";
@import "../node_modules/bootstrap/scss/reboot";
@import "../node_modules/bootstrap/scss/type";
@import "../node_modules/bootstrap/scss/images";
@import "../node_modules/bootstrap/scss/containers";
@import "../node_modules/bootstrap/scss/grid";
// @import "../node_modules/bootstrap/scss/tables";
@import "../node_modules/bootstrap/scss/forms";
@import "../node_modules/bootstrap/scss/buttons";
@import "../node_modules/bootstrap/scss/transitions";
// @import "../node_modules/bootstrap/scss/dropdown";
// @import "../node_modules/bootstrap/scss/button-group";
@import "../node_modules/bootstrap/scss/nav";
@import "../node_modules/bootstrap/scss/navbar";
@import "../node_modules/bootstrap/scss/card";
// @import "../node_modules/bootstrap/scss/accordion";
// @import "../node_modules/bootstrap/scss/breadcrumb";
// @import "../node_modules/bootstrap/scss/pagination";
// @import "../node_modules/bootstrap/scss/badge";
// @import "../node_modules/bootstrap/scss/alert";
// @import "../node_modules/bootstrap/scss/progress";
// @import "../node_modules/bootstrap/scss/list-group";
// @import "../node_modules/bootstrap/scss/close";
// @import "../node_modules/bootstrap/scss/toasts";
// @import "../node_modules/bootstrap/scss/modal";
// @import "../node_modules/bootstrap/scss/tooltip";
// @import "../node_modules/bootstrap/scss/popover";
// @import "../node_modules/bootstrap/scss/carousel";
// @import "../node_modules/bootstrap/scss/spinners";
// Helpers
@import "../node_modules/bootstrap/scss/helpers";
// Utilities
@import "../node_modules/bootstrap/scss/utilities/api";

26
assets/css/_fonts.scss Normal file
View file

@ -0,0 +1,26 @@
/* Fontsource Lato */
// @import "../node_modules/@fontsource/lato/100.css"; /* thin | normal */
// @import "../node_modules/@fontsource/lato/100-italic.css"; /* thin | italic */
@import "../node_modules/@fontsource/lato/300.css"; /* light | normal */
// @import "../node_modules/@fontsource/lato/300-italic.css"; /* light | italic */
@import "../node_modules/@fontsource/lato/400.css"; /* normal | normal */
// @import "../node_modules/@fontsource/lato/400-italic.css"; /* normal | italic */
@import "../node_modules/@fontsource/lato/700.css"; /* bold | normal */
// @import "../node_modules/@fontsource/lato/700-italic.css"; /* bold | italic */
// @import "../node_modules/@fontsource/lato/900.css"; /* black | normal */
// @import "../node_modules/@fontsource/lato/900-italic.css"; /* black | italic */
/* Fontsource Righteous */
@import "../node_modules/@fontsource/righteous/400.css"; /* normal | normal */
/* Fontsource Fira Mono */
@import "../node_modules/@fontsource/fira-mono/400.css"; /* normal | normal */
// @import "../node_modules/@fontsource/fira-mono/500.css"; /* heavier normal? */
@import "../node_modules/@fontsource/fira-mono/700.css"; /* bold | normal */
/* Fontsource Fira Code */
@import "../node_modules/@fontsource/fira-code/300.css"; /* light | normal */
@import "../node_modules/@fontsource/fira-code/400.css"; /* normal | normal */
// @import "../node_modules/@fontsource/fira-code/500.css"; /* heavier normal? */
// @import "../node_modules/@fontsource/fira-code/600.css"; /* heavier normal? */
@import "../node_modules/@fontsource/fira-code/700.css"; /* bold | normal */

View file

@ -0,0 +1,56 @@
/* Hamburger settings overrides */
$hamburger-padding-x: 0.95rem !default;
$hamburger-padding-y: 0.625rem !default;
$hamburger-layer-width: 1.5rem !default;
$hamburger-layer-height: 2px !default;
$hamburger-layer-spacing: 6px !default;
// * skipping default color, using color from bootstrap instead, below
// $hamburger-layer-color: rgba(0, 0, 0, 0.55) !default;
$hamburger-layer-border-radius: 0.25rem !default;
$hamburger-hover-opacity: 0.7 !default;
// * skipping default color, using color from bootstrap instead, below
// $hamburger-active-layer-color: $hamburger-layer-color !default;
$hamburger-active-hover-opacity: $hamburger-hover-opacity !default;
/* import hamburgers sass */
@import "../node_modules/hamburgers/_sass/hamburgers/hamburgers.scss";
/* correct colors to match bootstrap defaults */
.navbar-light {
.hamburger {
&.navbar-toggler {
border: 1px $navbar-light-toggler-border-color solid !important;
.hamburger-inner {
&,
&::before,
&::after {
background-color: $navbar-light-color;
}
}
&.is-active {
.hamburger-inner::after {
background-color: $navbar-light-color;
}
}
}
}
}
.navbar-dark {
.hamburger {
&.navbar-toggler {
border: 1px $navbar-dark-toggler-border-color solid !important;
.hamburger-inner {
&,
&::before,
&::after {
background-color: $navbar-dark-color;
}
}
&.is-active {
.hamburger-inner::after {
background-color: $navbar-dark-color;
}
}
}
}
}

View file

@ -0,0 +1,43 @@
/* LiveView specific classes for your customizations */
/* hides the feedback field help if liveview indicates field not touched yet */
.phx-no-feedback.invalid-feedback,
.phx-no-feedback .invalid-feedback,
.phx-orphaned-feedback.phx-no-feedback .invalid-feedback {
display: none;
}
.phx-orphaned-feedback .invalid-feedback {
display: block !important;
}
/* sets default bootstrap form-control styles if field not touched yet */
.phx-no-feedback .form-control.is-valid,
.phx-no-feedback .form-control.is-invalid {
border: $input-border-width solid $input-border-color;
background-image: none;
&:focus {
color: $input-focus-color;
background-color: $input-focus-bg;
border-color: $input-focus-border-color;
outline: 0;
@if $enable-shadows {
@include box-shadow($input-box-shadow, $input-focus-box-shadow);
} @else {
// Avoid using mixin so we can pass custom focus shadow properly
box-shadow: $input-focus-box-shadow;
}
}
}
.phx-click-loading {
opacity: 0.5;
transition: opacity 1s ease-out;
}
.phx-disconnected {
cursor: wait;
}
.phx-disconnected * {
pointer-events: none;
}

View file

@ -0,0 +1,21 @@
/*
SVG ICON SYSTEM
per https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4
*/
.icon {
display: inline-flex;
align-self: center;
}
.icon svg,
.icon img {
height: 1em;
width: 1em;
fill: currentColor;
}
.icon.baseline svg,
.icon img {
top: 0.125em;
position: relative;
}

View file

@ -1,90 +1,63 @@
/* This file is for your main application css. */
@import "./phoenix.css";
/* Fonts */
@import "fonts";
/* LiveView specific classes for your customizations */
.phx-no-feedback.invalid-feedback,
.phx-no-feedback .invalid-feedback {
display: none;
/* Load Bootstrap v5 and customizations */
@import "bs-load";
/*SVG ICON SYSTEM*/
@import "svg-icons";
/* LiveView specific CSS */
@import "phx-liveview";
/* Navbar toggler icon override */
@import "nav-burger";
/* extra */
.was-validated .no-valid-style .form-check-input:valid,
.form-check-input.is-valid {
border-color: inherit !important;
}
.was-validated .no-valid-style .form-check-input:valid ~ .form-check-label,
.no-valid-style .form-check-input.is-valid ~ .form-check-label {
color: inherit !important;
}
.table-nonfluid {
width: auto !important;
}
.cursor-pointer {
cursor: pointer !important;
}
.phx-click-loading {
opacity: 0.5;
transition: opacity 1s ease-out;
/*
icons in input fields
*/
/* enable absolute positioning */
.inner-addon {
position: relative;
}
.phx-disconnected{
cursor: wait;
}
.phx-disconnected *{
/* style icon */
.inner-addon > .icon {
position: absolute;
padding: 0.5625rem 0.5rem;
pointer-events: none;
}
.phx-modal {
opacity: 1!important;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
/* align icon */
.inner-addon > .icon.is-left {
left: 0px;
}
.inner-addon > .icon.is-right {
right: 0px;
}
.phx-modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
/* add padding */
.left-addon input,
.left-addon select {
padding-left: 2rem;
}
.phx-modal-close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.phx-modal-close:hover,
.phx-modal-close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
/* Alerts and form errors */
.alert {
padding: 15px;
margin-bottom: 20px;
border: 1px solid transparent;
border-radius: 4px;
}
.alert-info {
color: #31708f;
background-color: #d9edf7;
border-color: #bce8f1;
}
.alert-warning {
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faebcc;
}
.alert-danger {
color: #a94442;
background-color: #f2dede;
border-color: #ebccd1;
}
.alert p {
margin-bottom: 0;
}
.alert:empty {
display: none;
}
.invalid-feedback {
color: #a94442;
display: block;
margin: -1rem 0 2rem;
.right-addon input,
.right-addon select {
padding-right: 2rem;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,12 @@
const togglerBtn = document.getElementById("navbarSupportedContentToggler");
const navbarContent = document.getElementById("navbarSupportedContent");
navbarContent.addEventListener("show.bs.collapse", () => {
console.log("opening navbar content");
togglerBtn.classList.toggle("is-active");
});
navbarContent.addEventListener("hide.bs.collapse", () => {
console.log("closing navbar content");
togglerBtn.classList.toggle("is-active");
});

View file

@ -1,7 +1,12 @@
// We need to import the CSS so that webpack will load it.
// The MiniCssExtractPlugin is used to separate it out into
// its own CSS file.
import "../css/app.scss"
import "../css/app.scss";
// Import icons for sprite-loader
// navbar brand icon
import "../node_modules/@mdi/svg/svg/desktop-classic.svg"; // brand
// other:///
// webpack automatically bundles all modules in your
// entry points. Those entry points can be configured
@ -12,25 +17,34 @@ import "../css/app.scss"
// import {Socket} from "phoenix"
// import socket from "./socket"
//
import "phoenix_html"
import {Socket} from "phoenix"
import topbar from "topbar"
import {LiveSocket} from "phoenix_live_view"
import "phoenix_html";
import { Socket } from "phoenix";
import topbar from "topbar";
import { LiveSocket } from "phoenix_live_view";
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
// // Bootstrap v5 js imports
import "bootstrap/js/dist/collapse";
// import "bootstrap/js/dist/dropdown";
// Bootstrap helpers
import "./_hamburger-helper";
let csrfToken = document
.querySelector("meta[name='csrf-token']")
.getAttribute("content");
let liveSocket = new LiveSocket("/live", Socket, {
params: { _csrf_token: csrfToken },
});
// Show progress bar on live navigation and form submits
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
window.addEventListener("phx:page-loading-start", info => topbar.show())
window.addEventListener("phx:page-loading-stop", info => topbar.hide())
topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" });
window.addEventListener("phx:page-loading-start", (info) => topbar.show());
window.addEventListener("phx:page-loading-stop", (info) => topbar.hide());
// connect if there are any LiveViews on the page
liveSocket.connect()
liveSocket.connect();
// expose liveSocket on window for web console debug logs and latency simulation:
// >> liveSocket.enableDebug()
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
// >> liveSocket.disableLatencySim()
window.liveSocket = liveSocket
window.liveSocket = liveSocket;

13754
assets/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -3,28 +3,43 @@
"description": " ",
"license": "MIT",
"scripts": {
"deploy": "webpack --mode production",
"deploy": "NODE_ENV=production webpack --mode production",
"watch": "webpack --mode development --watch"
},
"dependencies": {
"@fontsource/fira-code": "^4.x",
"@fontsource/fira-mono": "^4.x",
"@fontsource/lato": "^4.x",
"@fontsource/righteous": "^4.x",
"@mdi/svg": "^5.9.55",
"@popperjs/core": "^2.8.4",
"bootstrap": "^5.0.0-beta3",
"bootstrap-icons": "^1.4.0",
"hamburgers": "^1.1.3",
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html",
"phoenix_live_view": "file:../deps/phoenix_live_view",
"topbar": "^0.1.4"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-loader": "^8.0.0",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "^3.4.2",
"hard-source-webpack-plugin": "^0.13.1",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.1",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"sass-loader": "^8.0.2",
"terser-webpack-plugin": "^2.3.2",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.2"
"@babel/core": "^7.x",
"@babel/preset-env": "^7.x",
"autoprefixer": "^10.2.4",
"babel-loader": "^8.x",
"copy-webpack-plugin": "^8.x",
"css-loader": "^5.x",
"css-minimizer-webpack-plugin": "^1.x",
"file-loader": "^6.2.0",
"glob-all": "^3.2.1",
"mini-css-extract-plugin": "^1.x",
"postcss": "^8.2.6",
"postcss-loader": "^5.0.0",
"postcss-scss": "^3.0.4",
"purgecss-webpack-plugin": "^4.0.2",
"sass": "^1.x",
"sass-loader": "^11.x",
"svg-sprite-loader": "^6.x",
"webpack": "^5.x",
"webpack-cli": "^4.x"
}
}

4
assets/postcss.config.js Normal file
View file

@ -0,0 +1,4 @@
module.exports = {
parser: require("postcss-scss"),
plugins: [require("autoprefixer")],
};

View file

@ -1,53 +1,105 @@
const path = require('path');
const glob = require('glob');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const path = require("path");
const glob = require("glob-all");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const SpriteLoaderPlugin = require("svg-sprite-loader/plugin");
const PurgecssPlugin = require("purgecss-webpack-plugin");
module.exports = (env, options) => {
const devMode = options.mode !== 'production';
const devMode = options.mode !== "production";
return {
optimization: {
minimizer: [
new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }),
new OptimizeCSSAssetsPlugin({})
]
},
entry: {
'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
app: glob.sync("./vendor/**/*.js").concat(["./js/app.js"]),
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, '../priv/static/js'),
publicPath: '/js/'
path: path.resolve(__dirname, "../priv/static/js"),
filename: "[name].js",
publicPath: "/js/",
},
devtool: devMode ? 'eval-cheap-module-source-map' : undefined,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
loader: "babel-loader",
},
},
{
test: /\.[s]?css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
"css-loader",
"sass-loader",
"postcss-loader",
],
}
]
},
{
test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader",
options: {
esModule: false,
name: "[name].[ext]",
outputPath: "../fonts",
},
},
],
},
{
test: /\.svg$/,
loader: "svg-sprite-loader",
options: {
extract: true,
spriteFilename: "icons.svg",
publicPath: "../images/",
symbolId: (filePath) => {
if (filePath.includes("bootstrap-icons")) {
return `bi-${path.basename(filePath).slice(0, -4)}`;
} else if (filePath.includes("@mdi")) {
return `mdi-${path.basename(filePath).slice(0, -4)}`;
} else if (filePath.includes("heroicons")) {
if (filePath.includes("outline")) {
return `hio-${path.basename(filePath).slice(0, -4)}`;
} else {
return `his-${path.basename(filePath).slice(0, -4)}`;
}
} else {
return `${path.basename(filePath).slice(0, -4)}`;
}
},
},
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
]
.concat(devMode ? [new HardSourceWebpackPlugin()] : [])
}
new MiniCssExtractPlugin({ filename: "../css/app.css" }),
new SpriteLoaderPlugin({ plainSprite: true }),
new CopyWebpackPlugin({
patterns: [{ from: "static/", to: "../" }],
}),
].concat(
devMode
? []
: [
new PurgecssPlugin({
paths: glob.sync([
"../**/*.html.leex",
"../**/*.html.eex",
"../**/views/**/*.ex",
"../**/live/**/*.ex",
"./js/**/*.js",
]),
safelist: [/phx/, /topbar/],
}),
]
),
optimization: {
minimizer: ["...", new CssMinimizerPlugin()],
},
devtool: devMode ? "source-map" : undefined,
};
};