Rewrite site with 11ty
This commit is contained in:
parent
815d89ad49
commit
3da1f74f98
56 changed files with 5242 additions and 911 deletions
1
src/_data/layout.js
Normal file
1
src/_data/layout.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
module.exports = "../_includes/layouts/layout.njk";
|
||||
46
src/_data/projects.json
Normal file
46
src/_data/projects.json
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
[
|
||||
{
|
||||
"name": "Start",
|
||||
"description": "A new tab page that displays lists of links using the browser’s indexedDB to store all data",
|
||||
"links": [
|
||||
{
|
||||
"title": "Site",
|
||||
"url": "https://start.neilbrommer.com/"
|
||||
},
|
||||
{
|
||||
"title": "Source Code",
|
||||
"url": "https://github.com/NeilBrommer/NewTabPage"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Blazor Start",
|
||||
"description": "A work in progress rewrite of the Start project using Blazor WebAssembly",
|
||||
"links": [
|
||||
{
|
||||
"title": "Source Code",
|
||||
"url": "https://github.com/NeilBrommer/BlazorStart"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Website",
|
||||
"description": "The source code for this website",
|
||||
"links": [
|
||||
{
|
||||
"title": "Source Code",
|
||||
"url": "https://github.com/NeilBrommer/Personal-Site"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Auto Dark",
|
||||
"description": "A small utility for setting/toggling the Windows 10 dark theme. Useful in combination with the Windows Task Scheduler to automatically change the theme.",
|
||||
"links": [
|
||||
{
|
||||
"title": "Source Code",
|
||||
"url": "https://github.com/NeilBrommer/WindowsAutoDark"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
17
src/_data/socialLinks.json
Normal file
17
src/_data/socialLinks.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
[
|
||||
{
|
||||
"name": "GitHub",
|
||||
"icon": "github",
|
||||
"url": "https://github.com/NeilBrommer"
|
||||
},
|
||||
{
|
||||
"name": "CodePen",
|
||||
"icon": "codepen",
|
||||
"url": "https://codepen.io/NeilBrommer"
|
||||
},
|
||||
{
|
||||
"name": "LinkedIn",
|
||||
"icon": "linkedin",
|
||||
"url": "https://www.linkedin.com/in/neilbrommer/"
|
||||
}
|
||||
]
|
||||
87
src/_includes/layouts/layout.njk
Normal file
87
src/_includes/layouts/layout.njk
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="author" content="Neil Brommer">
|
||||
<meta name="description" content="The personal website of Neil Brommer">
|
||||
|
||||
<title>
|
||||
{% if (title is defined) and (page.url != "/") %}
|
||||
{{ title }} - Neil Brommer
|
||||
{% else %}
|
||||
Neil Brommer
|
||||
{% endif %}
|
||||
</title>
|
||||
|
||||
<link rel="stylesheet" href="{{ '/css/site.css' | url }}">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="navbar" aria-label="Main Menu">
|
||||
<ul class="siteNav">
|
||||
{% for section in collections.MainPage | filterDrafts | eleventyNavigation %}
|
||||
<li {% if section.url == page.url %}class="active"{% endif %}>
|
||||
<a href="/#{{ section.title | slugify }}">
|
||||
{% if section.icon is defined %}
|
||||
<svg class="bi" fill="currentColor" role="img">
|
||||
<use xlink:href="/images/fontawesome/solid.svg#{{ section.icon }}" />
|
||||
</svg>
|
||||
{% endif %}
|
||||
{{ section.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
||||
{% set standalonePages = collections.all | filterDrafts | IsNotMainPageSection | eleventyNavigation %}
|
||||
|
||||
{% if standalonePages | length %}
|
||||
<li><hr /></li>
|
||||
|
||||
{% for standalonePage in standalonePages %}
|
||||
<li {% if standalonePage.url == page.url %}class="active"{% endif %}>
|
||||
<a href="{{ standalonePage.url }}">
|
||||
{% if standalonePage.icon is defined %}
|
||||
<svg class="bi" fill="currentColor" role="img">
|
||||
<use xlink:href="/images/fontawesome/solid.svg#{{ standalonePage.icon }}" />
|
||||
</svg>
|
||||
{% endif %}
|
||||
|
||||
{{ standalonePage.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<ul class="externalNav">
|
||||
{% for externalLink in socialLinks %}
|
||||
<li>
|
||||
<a href="{{ externalLink.url }}" title="{{ externalLink.name }}">
|
||||
<svg class="bi" fill="currentColor" role="img">
|
||||
<use xlink:href="/images/fontawesome/brands.svg#{{ externalLink.icon }}" />
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<h1 id="{{ title | slugify }}">
|
||||
{{ title }}
|
||||
|
||||
<button class="sidebar-toggle" onclick="setSidebar()">
|
||||
<svg class="bi" fill="currentColor" role="img" aria-label="Toggle Main Menu">
|
||||
<use xlink:href="/images/bootstrap-icons.svg#layout-sidebar-inset" />
|
||||
</svg>
|
||||
</button>
|
||||
</h1>
|
||||
|
||||
{{ content | safe }}
|
||||
</main>
|
||||
|
||||
<script type="text/javascript" src="/js/site.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
30
src/_sections/Colors.njk
Normal file
30
src/_sections/Colors.njk
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
title: Colors
|
||||
eleventyNavigation:
|
||||
key: Colors
|
||||
icon: eye-dropper
|
||||
order: 3
|
||||
tags: [ "MainPage" ]
|
||||
sectionOrder: 3
|
||||
draft: true
|
||||
---
|
||||
|
||||
<div class="color-blocks">
|
||||
<div class="color-block" style="background-color: var(--primary-dark-color); color: white;">
|
||||
Primary Dark
|
||||
</div>
|
||||
<div class="color-block" style="background-color: var(--primary-color); color: white;">
|
||||
Primary
|
||||
</div>
|
||||
<div class="color-block" style="background-color: var(--primary-light-color); color: black;">
|
||||
Primary Light
|
||||
</div>
|
||||
<div class="color-block" style="background-color: var(--complementary-color); color: black">
|
||||
Complementary
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input type="checkbox" id="testCheckBox" name="testCheckBox" checked />
|
||||
<label for="testCheckBox">This checkbox has the accent color</label>
|
||||
</div>
|
||||
11
src/_sections/Contact.md
Normal file
11
src/_sections/Contact.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: Contact
|
||||
eleventyNavigation:
|
||||
key: Contact
|
||||
icon: envelope
|
||||
order: 2
|
||||
tags: [ "MainPage" ]
|
||||
sectionOrder: 2
|
||||
---
|
||||
|
||||
Send an email to `contact @ this site`
|
||||
25
src/_sections/Projects.njk
Normal file
25
src/_sections/Projects.njk
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: Projects
|
||||
eleventyNavigation:
|
||||
key: Projects
|
||||
icon: screwdriver-wrench
|
||||
order: 1
|
||||
tags: [ "MainPage" ]
|
||||
sectionOrder: 1
|
||||
---
|
||||
|
||||
<div class="row-lg-3">
|
||||
{% for project in projects %}
|
||||
<section class="col card">
|
||||
<h3>{{ project.name }}</h3>
|
||||
<p>{{ project.description }}</p>
|
||||
<ul class="card-links">
|
||||
{% for link in project.links %}
|
||||
<li>
|
||||
<a href="{{ link.url }}" target="_blank">{{ link.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
{% endfor %}
|
||||
</div>
|
||||
3
src/_sections/_sections.11tydata.json
Normal file
3
src/_sections/_sections.11tydata.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"permalink": false
|
||||
}
|
||||
7
src/_sections/main.md
Normal file
7
src/_sections/main.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Neil Brommer
|
||||
sectionOrder: 0
|
||||
tags: [ "MainPage" ]
|
||||
---
|
||||
|
||||
Full-stack web developer at [Washington State University](https://wsu.edu)
|
||||
71
src/css/Components/_base.scss
Normal file
71
src/css/Components/_base.scss
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
@use '_variables';
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", sans-serif;
|
||||
line-height: 1.5;
|
||||
color: var(--text-color);
|
||||
background-color: var(--background-color);
|
||||
accent-color: var(--primary-color);
|
||||
|
||||
@media (min-width: #{variables.$sidebar-breakpoint}) {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
height: 100dvh;
|
||||
flex: 0 0 var(--sidebar-width);
|
||||
}
|
||||
|
||||
main {
|
||||
width: 100%;
|
||||
max-width: 70em;
|
||||
padding: 2rem;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 2px;
|
||||
text-underline-offset: 0.25em;
|
||||
text-decoration-color: transparent;
|
||||
transition: text-decoration-color 200ms ease;
|
||||
|
||||
&:hover,
|
||||
&:active {
|
||||
text-decoration-color: var(--primary-color);
|
||||
}
|
||||
|
||||
@media (prefers-contrast: more) {
|
||||
color: var(--primary-color-dark);
|
||||
text-decoration-color: var(--primary-color);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
text-decoration-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
height: 1px;
|
||||
background-color: var(--primary-border-color);
|
||||
}
|
||||
5
src/css/Components/_bootstrap-icons.scss
Normal file
5
src/css/Components/_bootstrap-icons.scss
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// this allows changing the size using font-size
|
||||
.bi {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
46
src/css/Components/_card.scss
Normal file
46
src/css/Components/_card.scss
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
@use '_variables';
|
||||
|
||||
.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border: solid 1px var(--primary-border-color);
|
||||
border-radius: var(--main-border-radius);
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.card-links {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5em;
|
||||
margin: auto -1rem -1rem -1rem;
|
||||
padding: 0.5rem;
|
||||
border-top: solid 1px var(--primary-border-color);
|
||||
list-style: none;
|
||||
|
||||
li a {
|
||||
display: inline-block;
|
||||
padding: 0.5em 1em;
|
||||
text-decoration: none;
|
||||
border-radius: var(--main-border-radius);
|
||||
transition: background-color 200ms ease;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: var(--nav-hover-background);
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-contrast: more),
|
||||
(prefers-reduced-motion: reduce) {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/css/Components/_code.scss
Normal file
19
src/css/Components/_code.scss
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
@use 'variables';
|
||||
|
||||
$code-background-color: darken(variables.$background-color, 5%);
|
||||
$code-background-color-dark: lighten(variables.$background-color-dark, 5%);
|
||||
|
||||
:root {
|
||||
--code-background: #{$code-background-color};
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
--code-background: #{$code-background-color-dark};
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
background: var(--code-background);
|
||||
padding: 0.125em 0.25em;
|
||||
border: solid 1px var(--primary-border-color);
|
||||
border-radius: calc(var(--main-border-radius) / 2);
|
||||
}
|
||||
22
src/css/Components/_color-block.scss
Normal file
22
src/css/Components/_color-block.scss
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
@use '_variables';
|
||||
|
||||
.color-blocks {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.color-block {
|
||||
flex: 1 1 0;
|
||||
height: 100px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
border: solid 1px var(--primary-border-color);
|
||||
border-radius: var(--main-border-radius);
|
||||
padding: 0.5em;
|
||||
}
|
||||
61
src/css/Components/_columns.scss
Normal file
61
src/css/Components/_columns.scss
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
@use '_variables';
|
||||
|
||||
:root {
|
||||
--column-spacing: 1.5em;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--column-spacing);
|
||||
|
||||
.col {
|
||||
flex: 0 0 100%;
|
||||
|
||||
// Default to md
|
||||
@media (min-width: #{variables.$size-md}) {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin row($name, $breakpoint) {
|
||||
.row-#{$name} {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
gap: var(--column-spacing);
|
||||
|
||||
.col {
|
||||
flex: 0 0 100%;
|
||||
|
||||
@media (min-width: #{$breakpoint}) {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
.row-#{$name}-#{$i} {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--column-spacing);
|
||||
|
||||
.col {
|
||||
flex: 0 0 100%;
|
||||
|
||||
@media (min-width: #{$breakpoint}) {
|
||||
// Even width filling the whole row accounting for gap
|
||||
flex: 0 0 calc((100% / #{$i}) - (var(--column-spacing) / #{$i} * (#{$i} - 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include row("xs", #{variables.$size-xs});
|
||||
@include row("sm", #{variables.$size-sm});
|
||||
@include row("md", #{variables.$size-md});
|
||||
@include row("lg", #{variables.$size-lg});
|
||||
@include row("xl", #{variables.$size-xl});
|
||||
@include row("2x", #{variables.$size-2x});
|
||||
8
src/css/Components/_headings.scss
Normal file
8
src/css/Components/_headings.scss
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 500;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
}
|
||||
18
src/css/Components/_lists.scss
Normal file
18
src/css/Components/_lists.scss
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
ul {
|
||||
padding-inline-start: 1.5rem;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
dl {
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dd {
|
||||
padding: 0.25em 0;
|
||||
margin-inline-start: 1em;
|
||||
}
|
||||
}
|
||||
43
src/css/Components/_mobile-header.scss
Normal file
43
src/css/Components/_mobile-header.scss
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
@use 'variables';
|
||||
|
||||
h1 {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
font-size: 2rem;
|
||||
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
background-color: var(--background-color);
|
||||
border: solid 1px var(--primary-border-color);
|
||||
border-radius: var(--main-border-radius);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.25em;
|
||||
margin: 0.25em;
|
||||
|
||||
transition: background-color 200ms ease, color 200ms ease;
|
||||
|
||||
&:hover, &focus {
|
||||
color: var(--primary-color);
|
||||
background-color: var(--nav-hover-background);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--primary-light-color);
|
||||
}
|
||||
|
||||
@media (min-width: #{variables.$sidebar-breakpoint}) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
117
src/css/Components/_navbar.scss
Normal file
117
src/css/Components/_navbar.scss
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
@use 'sass:color';
|
||||
@use '_variables';
|
||||
|
||||
header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: calc((var(--sidebar-width) + 2rem) * -1);
|
||||
height: calc(100dvh - 2rem); // Account for margin
|
||||
margin: 1rem;
|
||||
|
||||
border: solid 1px var(--primary-border-color);
|
||||
border-radius: var(--main-border-radius);
|
||||
background-color: rgba(var(--background-color-components), 0.5);
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
// Goes slightly past the end, then bounces back to the final position
|
||||
transition: left 250ms cubic-bezier(.44,1.36,.74,.97);
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
@media (prefers-contrast: more) {
|
||||
backdrop-filter: none;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
&[aria-hidden="false"] {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
@media (min-width: #{variables.$sidebar-breakpoint}) {
|
||||
// Always show the sidebar on larger screens
|
||||
position: sticky;
|
||||
left: unset;
|
||||
height: 100dvh;
|
||||
margin: 0;
|
||||
|
||||
border: none;
|
||||
background-color: unset;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
}
|
||||
|
||||
nav.navbar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
width: var(--sidebar-width);
|
||||
height: 100%;
|
||||
padding: 1rem;
|
||||
overflow: scroll;
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
|
||||
li {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
ul.siteNav {
|
||||
flex-direction: column;
|
||||
justify-items: flex-start;
|
||||
gap: 0.5em;
|
||||
|
||||
li {
|
||||
a {
|
||||
// Use flex to correct icon alignment
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
column-gap: 0.5em;
|
||||
width: 100%;
|
||||
padding: 0.75em;
|
||||
color: var(--nav-link-color);
|
||||
border-radius: var(--main-border-radius);
|
||||
|
||||
transition: background-color 200ms ease;
|
||||
}
|
||||
|
||||
&.active a {
|
||||
background-color: var(--nav-active-background);
|
||||
}
|
||||
|
||||
&:not(.active) a:hover, &:not(.active) a:focus {
|
||||
background-color: var(--nav-hover-background);
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.externalNav {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 0.5em;
|
||||
|
||||
li {
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: 0 0.75em;
|
||||
color: var(--nav-link-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
95
src/css/Components/_variables.scss
Normal file
95
src/css/Components/_variables.scss
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
@use 'sass:color';
|
||||
|
||||
@function select-foreground($backgroundColor, $lightColor: white, $darkColor: black) {
|
||||
@if (lightness($backgroundColor) > 60) {
|
||||
@return $darkColor;
|
||||
} @else {
|
||||
@return $lightColor;
|
||||
}
|
||||
}
|
||||
|
||||
$primary-r: 77;
|
||||
$primary-g: 94;
|
||||
$primary-b: 193;
|
||||
$primary-color: rgb($primary-r, $primary-g, $primary-b);
|
||||
$primary-light-color: lighten($primary-color, 35%);
|
||||
$primary-dark-color: darken($primary-color, 10%);
|
||||
$complementary-color: color.complement($primary-color);
|
||||
|
||||
$text-color: #3b4351;
|
||||
$text-color-dark: white;
|
||||
$background-color-components: 255, 255, 255;
|
||||
$background-color: white;
|
||||
$background-color-dark-components: 33, 33, 36;
|
||||
$background-color-dark: rgb(33, 33, 36);
|
||||
|
||||
$main-border-radius: 8px;
|
||||
|
||||
$nav-active-background: rgba($primary-color, 0.15);
|
||||
$nav-active-background-dark: rgba($primary-color, 0.35);
|
||||
$nav-background-hover-color: rgba($primary-light-color, 0.2);
|
||||
$nav-background-hover-color-dark: rgba($primary-color, 0.2);
|
||||
$nav-link-color: $text-color;
|
||||
$nav-link-color-dark: $text-color-dark;
|
||||
|
||||
$primary-border-color: darken($background-color, 15%);
|
||||
$primary-border-color-dark: lighten($background-color-dark, 15%);
|
||||
$primary-border-color-contrast: darken($background-color, 50%);
|
||||
$primary-border-color-dark-contrast: lighten($background-color-dark, 50%);
|
||||
|
||||
$size-xs: 480px;
|
||||
$size-sm: 600px;
|
||||
$size-md: 840px;
|
||||
$size-lg: 960px;
|
||||
$size-xl: 1280px;
|
||||
$size-2x: 1440px;
|
||||
|
||||
$sidebar-width: 15rem;
|
||||
$sidebar-breakpoint: $size-md;
|
||||
|
||||
:root {
|
||||
--size-xs: 480px;
|
||||
--size-sm: 600px;
|
||||
--size-md: 840px;
|
||||
--size-lg: 960px;
|
||||
--size-xl: 1280px;
|
||||
--size-2x: 1440px;
|
||||
|
||||
--sidebar-width: #{$sidebar-width};
|
||||
--sidebar-breakpoint: #{$sidebar-breakpoint};
|
||||
--main-border-radius: #{$main-border-radius};
|
||||
|
||||
--primary-color: #{$primary-color};
|
||||
--primary-light-color: #{$primary-light-color};
|
||||
--primary-dark-color: #{$primary-dark-color};
|
||||
--complementary-color: #{$complementary-color};
|
||||
|
||||
--primary-border-color: #{$primary-border-color};
|
||||
|
||||
--text-color: #{$text-color};
|
||||
--background-color: #{$background-color};
|
||||
--background-color-components: #{$background-color-components};
|
||||
|
||||
--nav-link-color: #{$nav-link-color};
|
||||
--nav-active-background: #{$nav-active-background};
|
||||
--nav-hover-background: #{$nav-background-hover-color};
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
--text-color: #{$text-color-dark};
|
||||
--background-color: #{$background-color-dark};
|
||||
--background-color-components: #{$background-color-dark-components};
|
||||
--primary-border-color: #{$primary-border-color-dark};
|
||||
|
||||
--nav-link-color: #{$nav-link-color-dark};
|
||||
--nav-active-background: #{$nav-active-background-dark};
|
||||
--nav-hover-background: #{$nav-background-hover-color-dark};
|
||||
|
||||
@media (prefers-contrast: more) {
|
||||
--primary-border-color: #{$primary-border-color-dark-contrast};
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-contrast: more) {
|
||||
--primary-border-color: #{$primary-border-color-contrast};
|
||||
}
|
||||
}
|
||||
13
src/css/site.scss
Normal file
13
src/css/site.scss
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
@use 'normalize.css/normalize';
|
||||
|
||||
@use 'Components/_variables';
|
||||
@use 'Components/_base';
|
||||
@use 'Components/_bootstrap-icons';
|
||||
@use 'Components/_columns';
|
||||
@use 'Components/_navbar';
|
||||
@use 'Components/_headings';
|
||||
@use 'Components/_card';
|
||||
@use 'Components/_color-block';
|
||||
@use 'Components/_mobile-header';
|
||||
@use 'Components/_lists';
|
||||
@use 'Components/_code';
|
||||
18
src/index.njk
Normal file
18
src/index.njk
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
title: Neil Brommer
|
||||
eleventyNavigation:
|
||||
key: Neil Brommer
|
||||
icon: house
|
||||
order: 0
|
||||
tags: [ "MainPage" ]
|
||||
---
|
||||
|
||||
{% for section in collections.MainPage | filterDrafts | IsNotPage(page.url) | IsMainPageSection | orderBySectionOrder %}
|
||||
{% if not loop.first %}
|
||||
<h2 id="{{ section.data.title | slugify }}">{{ section.data.title }}</h2>
|
||||
{% endif %}
|
||||
|
||||
<section>
|
||||
{{ section.templateContent | safe }}
|
||||
</section>
|
||||
{% endfor %}
|
||||
48
src/js/site.js
Normal file
48
src/js/site.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
"use strict";
|
||||
|
||||
function dismissSidebarOnClick(event) {
|
||||
if (event.target.closest("header") == null && event.target.closest(".sidebar-toggle") == null) {
|
||||
event.stopPropagation();
|
||||
setSidebar(false);
|
||||
}
|
||||
}
|
||||
|
||||
function setSidebar(isOpen) {
|
||||
let header = document.querySelector("header");
|
||||
|
||||
// If isOpen isn't provided, then just toggle the sidebar
|
||||
if (isOpen == null) {
|
||||
let currentlyOpen = header.getAttribute("aria-hidden") == "false";
|
||||
isOpen = !currentlyOpen;
|
||||
}
|
||||
|
||||
header.setAttribute("aria-hidden", (!isOpen).toString());
|
||||
|
||||
if (isOpen) {
|
||||
document.querySelector("body")
|
||||
.addEventListener("click", dismissSidebarOnClick);
|
||||
} else {
|
||||
document.querySelector("body")
|
||||
.removeEventListener("click", dismissSidebarOnClick);
|
||||
}
|
||||
}
|
||||
|
||||
// Make main page sections active on scroll
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
entries.forEach(entry => {
|
||||
const id = entry.target.previousElementSibling.id;
|
||||
const menuListItem = document.querySelector(`nav li a[href="/#${id}"]`).parentElement;
|
||||
|
||||
if (entry.intersectionRatio > 0) {
|
||||
menuListItem.classList.add("active");
|
||||
} else {
|
||||
menuListItem.classList.remove("active");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll("h1[id] + section, h2[id] + section, h3[id] + section, h4[id] + section, h5[id] + section, h6[id] + section")
|
||||
.forEach(section => observer.observe(section));
|
||||
});
|
||||
48
src/resume.md
Normal file
48
src/resume.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
title: Resume
|
||||
eleventyNavigation:
|
||||
key: Resume
|
||||
icon: file-lines
|
||||
order: 2
|
||||
---
|
||||
|
||||
## Work History
|
||||
|
||||
[Washington State University](https://wsu.edu) [Division of Student Affairs](https://studentaffairs.wsu.edu/)
|
||||
|
||||
: Application Developer, 2018 - present
|
||||
: Created and maintained custom web applications either as standalone software or integrating with
|
||||
third party backends
|
||||
|
||||
|
||||
## Education
|
||||
|
||||
[Eastern Washington University](https://www.ewu.edu/)
|
||||
|
||||
: Bachelor of Science in Computer Science
|
||||
: 2014 - 2018
|
||||
|
||||
[Spokane Community College](https://scc.spokane.edu/)
|
||||
|
||||
: Associate of Applied Science in Network Design and Administration
|
||||
: 2011 - 2013
|
||||
|
||||
## Skills
|
||||
|
||||
* C# - .NET Framework and .NET 5+
|
||||
* [ASP.NET and ASP.NET Core](https://dotnet.microsoft.com/en-us/apps/aspnet) - [WebForms](https://learn.microsoft.com/en-us/aspnet/web-forms/what-is-web-forms), [MVC](https://dotnet.microsoft.com/en-us/apps/aspnet/mvc), [Razor Pages](https://learn.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-7.0&tabs=visual-studio), and [WebAPI](https://learn.microsoft.com/en-us/aspnet/core/web-api/)
|
||||
* Entity Framework and [Entity Framework Core](https://learn.microsoft.com/en-us/ef/core/)
|
||||
* [Blazor WebAssembly](https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor)
|
||||
* WinForms and WPF
|
||||
* Xamarin native for MacOS
|
||||
* Version control
|
||||
* Git
|
||||
* [Team Foundation Server/Azure DevOps Server](https://azure.microsoft.com/en-us/products/devops/server)
|
||||
* Web development
|
||||
* HTML, CSS, JavaScript, [SASS](https://sass-lang.com/), [TypeScript](https://www.typescriptlang.org/)
|
||||
* [React](https://react.dev/)
|
||||
* Create and consume REST APIs with [OpenAPI](https://www.openapis.org/), [Swashbuckle](https://github.com/domaindrivendev/Swashbuckle.AspNetCore), and [NSwag](https://github.com/RicoSuter/NSwag)
|
||||
* [WCF](https://learn.microsoft.com/en-us/dotnet/framework/wcf/whats-wcf)/SOAP
|
||||
* Web server administration
|
||||
* Linux (NGINX, Apache, Caddy) and Windows Server (IIS)
|
||||
* Continuous Integration and Continuous Deployment via [Azure DevOps Server](https://azure.microsoft.com/en-us/products/devops/server)
|
||||
Loading…
Add table
Add a link
Reference in a new issue