# Blueprint-Steampunk WebUI Styleguide
## Angular Material + SCSS Implementation
---
## Core Design Philosophy
A sophisticated WebUI that balances Victorian mechanical aesthetics with modern usability principles. The interface should feel like a digital workshop where brass gears meet clean code.
---
## Color System
### SCSS Color Variables
```scss
// Primary Palette
$primary-blueprint: #2C5282;
$primary-light: #4A90A4;
$primary-dark: #1E3A5F;
// Accent Palette
$accent-brass: #D4A574;
$accent-copper: #7C9885;
$accent-steam: #E8E8E8;
// Background System
$bg-paper: #FAFAF8;
$bg-blueprint: #F4F1E8;
$bg-dark-panel: #2D3748;
// Text Colors
$text-primary: #2D3748;
$text-secondary: #4A5568;
$text-hint: #718096;
$text-on-primary: #FFFFFF;
// State Colors
$success-patina: #48BB78;
$warning-brass: #ED8936;
$error-rust: #E53E3E;
$info-blueprint: $primary-light;
// Interactive States
$hover-overlay: rgba($primary-blueprint, 0.08);
$focus-glow: rgba($accent-brass, 0.25);
$disabled-opacity: 0.6;
```
### Angular Material Theme
```scss
@use '@angular/material' as mat;
$custom-primary: mat.define-palette((
50: #E6F0F7,
100: #C1D9EA,
200: #98C0DC,
300: #6FA6CE,
400: #5093C4,
500: $primary-blueprint,
600: #2773B3,
700: #2168AC,
800: #1B5EA5,
900: #104B99,
contrast: (
500: white,
600: white,
700: white,
800: white,
900: white,
)
));
$custom-accent: mat.define-palette((
50: #FAF5EE,
100: #F3E5D5,
200: #EBD4B9,
300: #E3C39D,
400: #DCB688,
500: $accent-brass,
600: #CF9D6C,
700: #C99361,
800: #C38A57,
900: #B97944,
contrast: (
500: $text-primary,
600: $text-primary,
700: white,
800: white,
900: white,
)
));
```
---
## Typography
### Font Stack
```scss
// Import in styles.scss
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500;700&family=Roboto:wght@300;400;500;700&family=Playfair+Display:ital@0;1&display=swap');
// Font Variables
$font-technical: 'Roboto Mono', monospace;
$font-primary: 'Roboto', sans-serif;
$font-decorative: 'Playfair Display', serif;
// Type Scale
$type-scale: (
'display': (
'size': 3rem,
'line-height': 1.2,
'weight': 300,
'letter-spacing': -0.02em
),
'h1': (
'size': 2rem,
'line-height': 1.3,
'weight': 400,
'letter-spacing': -0.01em
),
'h2': (
'size': 1.5rem,
'line-height': 1.4,
'weight': 500,
'letter-spacing': 0
),
'h3': (
'size': 1.25rem,
'line-height': 1.5,
'weight': 500,
'letter-spacing': 0.01em
),
'body': (
'size': 1rem,
'line-height': 1.6,
'weight': 400,
'letter-spacing': 0.02em
),
'caption': (
'size': 0.875rem,
'line-height': 1.4,
'weight': 400,
'letter-spacing': 0.03em
),
'overline': (
'size': 0.75rem,
'line-height': 1.5,
'weight': 500,
'letter-spacing': 0.08em,
'text-transform': uppercase
)
);
```
---
## Component Styling
### Material Components Override
#### Buttons
```scss
.mat-mdc-button,
.mat-mdc-raised-button {
font-family: $font-technical;
letter-spacing: 0.05em;
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(45deg, $accent-brass, $accent-copper);
opacity: 0;
transition: opacity 0.3s ease;
z-index: -1;
}
&:hover::before {
opacity: 0.1;
}
// Gear icon animation on hover
&.gear-button {
.mat-icon {
transition: transform 0.6s ease;
}
&:hover .mat-icon {
transform: rotate(180deg);
}
}
}
// Fancy primary button
.mat-mdc-raised-button.mat-primary {
box-shadow: 0 4px 6px rgba($primary-dark, 0.2);
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, transparent 30%, rgba(255,255,255,0.1) 50%, transparent 70%);
transform: translateX(-100%);
transition: transform 0.6s;
}
&:hover::after {
transform: translateX(100%);
}
}
```
#### Cards
```scss
.mat-mdc-card {
background: $bg-paper;
border: 1px solid rgba($primary-blueprint, 0.1);
position: relative;
// Blueprint grid background
&.blueprint-card {
background-image:
repeating-linear-gradient(0deg,
rgba($primary-blueprint, 0.03) 0px,
transparent 1px,
transparent 8px,
rgba($primary-blueprint, 0.03) 9px),
repeating-linear-gradient(90deg,
rgba($primary-blueprint, 0.03) 0px,
transparent 1px,
transparent 8px,
rgba($primary-blueprint, 0.03) 9px);
background-size: 8px 8px;
}
// Decorative corner brackets
&.fancy-corners {
&::before,
&::after {
content: '';
position: absolute;
width: 20px;
height: 20px;
border: 2px solid $accent-brass;
}
&::before {
top: -1px;
left: -1px;
border-right: none;
border-bottom: none;
}
&::after {
bottom: -1px;
right: -1px;
border-left: none;
border-top: none;
}
}
}
```
#### Form Fields
```scss
.mat-mdc-form-field {
font-family: $font-primary;
.mat-mdc-text-field-wrapper {
background-color: rgba($bg-paper, 0.8);
&:hover {
background-color: $bg-paper;
}
}
// Technical monospace for input values
input,
textarea {
font-family: $font-technical;
letter-spacing: 0.02em;
}
// Floating label animation
&.mat-focused {
.mat-mdc-floating-label {
color: $accent-brass;
font-weight: 500;
}
}
// Custom underline
.mat-mdc-form-field-focus-overlay {
background-color: $accent-brass;
}
}
```
#### Tables
```scss
.mat-mdc-table {
font-family: $font-technical;
background: $bg-paper;
.mat-mdc-header-row {
background: linear-gradient(to bottom, $bg-blueprint, $bg-paper);
border-bottom: 2px solid $primary-blueprint;
.mat-mdc-header-cell {
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: $primary-dark;
}
}
.mat-mdc-row {
&:nth-child(even) {
background-color: rgba($primary-blueprint, 0.02);
}
&:hover {
background-color: rgba($accent-brass, 0.05);
transform: translateX(2px);
transition: all 0.2s ease;
}
}
}
```
---
## Interactive Elements
### Playful Animations
```scss
// Mixin for steam effect
@mixin steam-animation {
@keyframes steam {
0% {
transform: translateY(0) scale(1);
opacity: 0.8;
}
100% {
transform: translateY(-20px) scale(1.5);
opacity: 0;
}
}
&::before {
content: '';
position: absolute;
width: 20px;
height: 20px;
background: radial-gradient(circle, $accent-steam 0%, transparent 70%);
animation: steam 2s ease-out infinite;
}
}
// Gear rotation mixin
@mixin gear-rotate($duration: 10s) {
animation: rotate $duration linear infinite;
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
}
// Loading spinner customization
.mat-mdc-progress-spinner {
&.steampunk-spinner {
circle {
stroke: $accent-brass;
}
&::after {
@include gear-rotate(2s);
content: '⚙';
position: absolute;
font-size: 24px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
```
### Hover Effects
```scss
// Fancy hover mixin
@mixin fancy-hover {
position: relative;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba($primary-dark, 0.15);
}
}
// Tooltip styling
.mat-mdc-tooltip {
background: $bg-dark-panel;
font-family: $font-technical;
font-size: 0.875rem;
padding: 8px 12px;
border: 1px solid $accent-brass;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
```
---
## Layout System
### Grid Framework
```scss
// Responsive grid mixin
@mixin blueprint-grid {
display: grid;
gap: 16px;
@media (min-width: 600px) {
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
}
@media (min-width: 960px) {
gap: 32px;
}
}
// Container sizing
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 16px;
@media (min-width: 600px) {
padding: 24px;
}
@media (min-width: 960px) {
padding: 32px;
}
}
```
### Spacing System
```scss
// Spacing scale
$spacing: (
'xs': 4px,
'sm': 8px,
'md': 16px,
'lg': 24px,
'xl': 32px,
'xxl': 48px
);
// Spacing utility classes
@each $name, $value in $spacing {
.m-#{$name} { margin: $value; }
.mt-#{$name} { margin-top: $value; }
.mr-#{$name} { margin-right: $value; }
.mb-#{$name} { margin-bottom: $value; }
.ml-#{$name} { margin-left: $value; }
.mx-#{$name} { margin-left: $value; margin-right: $value; }
.my-#{$name} { margin-top: $value; margin-bottom: $value; }
.p-#{$name} { padding: $value; }
.pt-#{$name} { padding-top: $value; }
.pr-#{$name} { padding-right: $value; }
.pb-#{$name} { padding-bottom: $value; }
.pl-#{$name} { padding-left: $value; }
.px-#{$name} { padding-left: $value; padding-right: $value; }
.py-#{$name} { padding-top: $value; padding-bottom: $value; }
}
```
---
## Accessibility & Usability
### Focus States
```scss
// Custom focus style
@mixin custom-focus {
&:focus {
outline: 2px solid $accent-brass;
outline-offset: 2px;
}
&:focus:not(:focus-visible) {
outline: none;
}
&:focus-visible {
outline: 2px solid $accent-brass;
outline-offset: 2px;
box-shadow: 0 0 0 4px rgba($accent-brass, 0.2);
}
}
// Apply to interactive elements
button,
a,
input,
select,
textarea {
@include custom-focus;
}
```
### High Contrast Support
```scss
@media (prefers-contrast: high) {
.mat-mdc-button {
border: 2px solid currentColor;
}
.mat-mdc-card {
border-width: 2px;
}
.blueprint-card {
background-image: none;
background-color: $bg-paper;
}
}
```
### Dark Mode
```scss
@media (prefers-color-scheme: dark) {
:root {
--bg-paper: #1A202C;
--bg-blueprint: #2D3748;
--text-primary: #E2E8F0;
--text-secondary: #A0AEC0;
}
.blueprint-card {
background-image:
repeating-linear-gradient(0deg,
rgba($accent-brass, 0.05) 0px,
transparent 1px,
transparent 8px,
rgba($accent-brass, 0.05) 9px),
repeating-linear-gradient(90deg,
rgba($accent-brass, 0.05) 0px,
transparent 1px,
transparent 8px,
rgba($accent-brass, 0.05) 9px);
}
}
```
---
## Special Components
### Gauge Component
```scss
.gauge-container {
position: relative;
width: 120px;
height: 120px;
.gauge-face {
width: 100%;
height: 100%;
border-radius: 50%;
background: radial-gradient(circle at 30% 30%, $bg-paper, $bg-blueprint);
border: 3px solid $accent-brass;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
}
.gauge-needle {
position: absolute;
width: 2px;
height: 50%;
background: $error-rust;
bottom: 50%;
left: 50%;
transform-origin: bottom center;
transition: transform 0.5s ease-out;
}
.gauge-value {
position: absolute;
bottom: 20%;
left: 50%;
transform: translateX(-50%);
font-family: $font-technical;
font-weight: 700;
color: $text-primary;
}
}
```
### Pipe Connector Animation
```scss
.pipe-connector {
position: relative;
height: 4px;
background: linear-gradient(to right, $accent-copper, $accent-brass);
&::before {
content: '';
position: absolute;
width: 20px;
height: 100%;
background: rgba(255, 255, 255, 0.6);
animation: flow 2s linear infinite;
}
@keyframes flow {
from {
left: -20px;
}
to {
left: 100%;
}
}
}
```
---
## Implementation Tips
### Performance Optimization
```scss
// Use CSS containment for complex components
.complex-widget {
contain: layout style paint;
}
// Reduce motion for accessibility
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
```
### Utility Classes
```scss
// Text utilities
.text-technical { font-family: $font-technical; }
.text-decorative { font-family: $font-decorative; }
.text-brass { color: $accent-brass; }
.text-blueprint { color: $primary-blueprint; }
// Background utilities
.bg-blueprint-pattern { @extend .blueprint-card; }
.bg-paper { background-color: $bg-paper; }
.bg-steam { background-color: $accent-steam; }
// Border utilities
.border-brass { border-color: $accent-brass; }
.border-dashed { border-style: dashed; }
.border-ornate {
border: 2px solid $accent-brass;
border-image: url('path/to/ornate-border.svg') 30 repeat;
}
```
---
## Best Practices
### Do's
- ✓ Use semantic HTML with ARIA labels
- ✓ Maintain consistent spacing using the grid system
- ✓ Apply hover states to all interactive elements
- ✓ Use CSS custom properties for dynamic theming
- ✓ Test with keyboard navigation
### Don'ts
- ✗ Overuse animations (max 3 concurrent)
- ✗ Make text smaller than 14px
- ✗ Use low contrast color combinations
- ✗ Forget loading states for async operations
- ✗ Ignore Angular Material's built-in accessibility
---
## Quick Start Template
```scss
// _variables.scss
@import 'theme-variables';
@import 'typography';
@import 'spacing';
// _mixins.scss
@import 'animation-mixins';
@import 'hover-effects';
@import 'focus-states';
// styles.scss
@use '@angular/material' as mat;
@import 'variables';
@import 'mixins';
@include mat.all-component-themes($theme);
// Component usage
.fancy-dashboard {
@include blueprint-grid;
.widget {
@include fancy-hover;
@extend .blueprint-card;
@extend .fancy-corners;
}
.status-gauge {
@include steam-animation;
}
}
```