Add SCSS styles for base, components, layouts, and utilities (not on

use)
This commit is contained in:
rafaeldpsilva
2025-09-02 16:19:20 +01:00
parent 1522f70f08
commit 044f301013
14 changed files with 1734 additions and 0 deletions

View File

@@ -0,0 +1,181 @@
// Responsive breakpoints
@mixin respond-above($breakpoint) {
@media (min-width: $breakpoint) {
@content;
}
}
@mixin respond-below($breakpoint) {
@media (max-width: #{$breakpoint - 1px}) {
@content;
}
}
// Flexbox utilities
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}
@mixin flex-between {
display: flex;
align-items: center;
justify-content: space-between;
}
@mixin flex-column {
display: flex;
flex-direction: column;
}
// Grid utilities
@mixin grid-responsive($columns-mobile: 1, $columns-tablet: 2, $columns-desktop: 3, $gap: $spacing-md) {
display: grid;
gap: $gap;
grid-template-columns: repeat($columns-mobile, 1fr);
@include respond-above($breakpoint-md) {
grid-template-columns: repeat($columns-tablet, 1fr);
}
@include respond-above($breakpoint-lg) {
grid-template-columns: repeat($columns-desktop, 1fr);
}
}
// Button mixins
@mixin button-base {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: $radius-md;
font-weight: 500;
transition: all $transition-fast;
cursor: pointer;
border: none;
text-decoration: none;
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
@mixin button-primary {
@include button-base;
background-color: $primary;
color: white;
&:hover:not(:disabled) {
background-color: $primary-dark;
}
}
@mixin button-secondary {
@include button-base;
background-color: $gray-100;
color: $gray-700;
border: 1px solid $gray-200;
&:hover:not(:disabled) {
background-color: $gray-200;
}
}
// Card mixins
@mixin card-base {
background-color: white;
border-radius: $radius-2xl;
box-shadow: $shadow-sm;
border: 1px solid $gray-100;
}
@mixin card-padding($size: md) {
@if $size == sm {
padding: $spacing-md;
} @else if $size == md {
padding: $spacing-lg;
} @else if $size == lg {
padding: $spacing-xl;
}
}
// Status indicators
@mixin status-indicator($color) {
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
background-color: $color;
}
// Sensor type styling
@mixin sensor-type-style($bg-color, $text-color) {
background-color: $bg-color;
color: $text-color;
padding: $spacing-sm;
border-radius: $radius-lg;
}
// Battery indicator
@mixin battery-indicator {
height: 0.25rem;
background-color: $gray-200;
border-radius: 9999px;
overflow: hidden;
.fill {
height: 100%;
border-radius: inherit;
transition: all $transition-normal;
&.good {
background-color: $battery-good;
}
&.warning {
background-color: $battery-warning;
}
&.critical {
background-color: $battery-critical;
}
}
}
// Custom slider
@mixin custom-slider {
width: 100%;
height: 0.5rem;
background-color: $gray-200;
border-radius: $radius-lg;
appearance: none;
cursor: pointer;
&::-webkit-slider-thumb {
appearance: none;
height: 1.25rem;
width: 1.25rem;
border-radius: 50%;
background: $primary;
cursor: pointer;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2);
}
&::-moz-range-thumb {
height: 1.25rem;
width: 1.25rem;
border-radius: 50%;
background: $primary;
cursor: pointer;
border: none;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.2);
}
}
// Truncate text
@mixin truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

View File

@@ -0,0 +1,83 @@
// Colors
$primary: #3b82f6;
$primary-light: #60a5fa;
$primary-dark: #2563eb;
$secondary: #6b7280;
$secondary-light: #9ca3af;
$secondary-dark: #4b5563;
$success: #10b981;
$warning: #f59e0b;
$danger: #ef4444;
$info: #06b6d4;
$gray-50: #f9fafb;
$gray-100: #f3f4f6;
$gray-200: #e5e7eb;
$gray-300: #d1d5db;
$gray-400: #9ca3af;
$gray-500: #6b7280;
$gray-600: #4b5563;
$gray-700: #374151;
$gray-800: #1f2937;
$gray-900: #111827;
// Status Colors
$status-online: #10b981;
$status-offline: #6b7280;
$status-error: #ef4444;
// Sensor Type Colors
$sensor-energy-bg: #fef3c7;
$sensor-energy-text: #b45309;
$sensor-co2-bg: #dcfce7;
$sensor-co2-text: #166534;
$sensor-temperature-bg: #fee2e2;
$sensor-temperature-text: #991b1b;
$sensor-humidity-bg: #dbeafe;
$sensor-humidity-text: #1e40af;
$sensor-hvac-bg: #cffafe;
$sensor-hvac-text: #155e75;
$sensor-lighting-bg: #fef3c7;
$sensor-lighting-text: #92400e;
$sensor-security-bg: #f3e8ff;
$sensor-security-text: #7c2d12;
// Battery Colors
$battery-good: #10b981;
$battery-warning: #f59e0b;
$battery-critical: #ef4444;
// Spacing
$spacing-xs: 0.25rem;
$spacing-sm: 0.5rem;
$spacing-md: 1rem;
$spacing-lg: 1.5rem;
$spacing-xl: 2rem;
$spacing-2xl: 3rem;
// Border Radius
$radius-sm: 0.375rem;
$radius-md: 0.5rem;
$radius-lg: 0.75rem;
$radius-xl: 1rem;
$radius-2xl: 1.5rem;
// Shadows
$shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
$shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
$shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
$shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
// Transitions
$transition-fast: 150ms ease-in-out;
$transition-normal: 300ms ease-in-out;
$transition-slow: 500ms ease-in-out;
// Breakpoints
$breakpoint-sm: 640px;
$breakpoint-md: 768px;
$breakpoint-lg: 1024px;
$breakpoint-xl: 1280px;
$breakpoint-2xl: 1536px;

View File

@@ -0,0 +1,34 @@
// CSS Reset and Base Styles
* {
box-sizing: border-box;
}
html {
line-height: 1.15;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
font-family:
ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
background-color: $gray-100;
color: $gray-900;
}
ul,
ol {
margin: 0;
padding: 0;
list-style: none;
}
button {
font-family: inherit;
}
a {
color: inherit;
text-decoration: none;
}

View File

@@ -0,0 +1,56 @@
// Typography Styles
h1, h2, h3, h4, h5, h6 {
margin: 0;
font-weight: 600;
}
h1 {
font-size: 2rem;
line-height: 1.2;
}
h2 {
font-size: 1.5rem;
line-height: 1.3;
}
h3 {
font-size: 1.25rem;
line-height: 1.4;
}
h4 {
font-size: 1.125rem;
line-height: 1.4;
}
h5 {
font-size: 1rem;
line-height: 1.5;
}
h6 {
font-size: 0.875rem;
line-height: 1.5;
}
p {
margin: 0;
line-height: 1.6;
}
// Text utilities
.text-xs { font-size: 0.75rem; }
.text-sm { font-size: 0.875rem; }
.text-base { font-size: 1rem; }
.text-lg { font-size: 1.125rem; }
.text-xl { font-size: 1.25rem; }
.text-2xl { font-size: 1.5rem; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.text-center { text-align: center; }
.text-left { text-align: left; }
.text-right { text-align: right; }

View File

@@ -0,0 +1,133 @@
// Button Base Styles
.btn {
@include button-base;
padding: $spacing-sm $spacing-md;
font-size: 0.875rem;
&--primary {
@include button-primary;
}
&--secondary {
@include button-secondary;
}
&--sm {
padding: $spacing-xs $spacing-sm;
font-size: 0.75rem;
}
&--md {
padding: $spacing-sm $spacing-md;
font-size: 0.875rem;
}
&--lg {
padding: $spacing-md $spacing-lg;
font-size: 1rem;
}
&--icon-only {
padding: $spacing-sm;
width: auto;
height: auto;
}
&--full-width {
width: 100%;
}
}
// Toggle Button Group
.toggle-group {
@include flex-center;
gap: $spacing-sm;
background-color: $gray-100;
border-radius: $radius-lg;
padding: $spacing-xs;
.toggle-btn {
padding: $spacing-sm * 1.5 $spacing-md;
border-radius: $radius-md;
font-size: 0.875rem;
font-weight: 500;
transition: all $transition-fast;
cursor: pointer;
border: none;
background: none;
@include flex-center;
gap: $spacing-xs;
&.active {
background-color: white;
color: $gray-900;
box-shadow: $shadow-sm;
}
&.inactive {
color: $gray-600;
&:hover {
color: $gray-900;
}
}
.icon {
width: 1rem;
height: 1rem;
}
}
}
// Action Buttons
.action-button {
@include flex-center;
gap: $spacing-sm;
padding: $spacing-sm $spacing-md;
border-radius: $radius-lg;
font-size: 0.875rem;
font-weight: 500;
transition: all $transition-fast;
cursor: pointer;
border: 1px solid $gray-200;
background-color: $gray-50;
color: $gray-700;
&:hover:not(:disabled) {
background-color: $gray-100;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.icon {
font-size: 1rem;
}
.text {
@include truncate;
}
}
// Close Button
.close-button {
padding: $spacing-sm;
border-radius: 50%;
transition: background-color $transition-fast;
background: none;
border: none;
cursor: pointer;
&:hover {
background-color: $gray-100;
}
.icon {
width: 1.25rem;
height: 1.25rem;
color: $gray-400;
}
}

View File

@@ -0,0 +1,452 @@
// Base Card Styles
.card {
@include card-base;
&--padding-sm {
@include card-padding(sm);
}
&--padding-md {
@include card-padding(md);
}
&--padding-lg {
@include card-padding(lg);
}
}
// Simple Sensor Card
.simple-sensor-card {
@include card-base;
@include card-padding(md);
&__header {
@include flex-between;
margin-bottom: $spacing-md;
}
&__info {
@include flex-center;
gap: $spacing-sm;
.icon-container {
padding: $spacing-sm * 1.5;
border-radius: $radius-lg;
}
.details {
h3 {
font-weight: 500;
color: $gray-900;
font-size: 0.875rem;
margin: 0;
}
p {
font-size: 0.75rem;
color: $gray-500;
margin: 0;
}
}
}
&__status {
@include flex-center;
gap: $spacing-xs;
.indicator {
@include status-indicator($status-offline);
&--online {
background-color: $status-online;
}
&--offline {
background-color: $status-offline;
}
&--error {
background-color: $status-error;
}
}
.label {
font-size: 0.75rem;
color: $gray-500;
text-transform: capitalize;
}
}
&__values {
margin-bottom: $spacing-md;
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: $spacing-sm;
.metric {
background-color: $gray-50;
border-radius: $radius-md;
padding: $spacing-sm;
.label {
color: $gray-600;
font-size: 0.75rem;
margin-bottom: $spacing-xs;
}
.value {
font-weight: 500;
color: $gray-900;
.unit {
color: $gray-500;
}
}
}
}
}
&__actions {
.title {
font-size: 0.75rem;
font-weight: 500;
color: $gray-600;
margin-bottom: $spacing-sm;
}
.buttons {
display: flex;
gap: $spacing-xs;
flex-wrap: wrap;
.action-btn {
@include flex-center;
gap: $spacing-xs;
padding: $spacing-xs $spacing-sm;
background-color: $gray-100;
color: $gray-700;
border-radius: $radius-md;
font-size: 0.75rem;
font-weight: 500;
transition: all $transition-fast;
border: none;
cursor: pointer;
&:hover:not(:disabled) {
background-color: $gray-200;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.icon {
font-size: 0.75rem;
}
.text {
@include truncate;
}
}
.more-btn {
@extend .action-btn;
background-color: #dbeafe;
color: #1e40af;
&:hover:not(:disabled) {
background-color: #bfdbfe;
}
}
}
}
&__monitor-only {
font-size: 0.75rem;
color: $gray-500;
text-align: center;
padding: $spacing-sm;
background-color: $gray-50;
border-radius: $radius-md;
}
}
// Detailed Sensor Card
.detailed-sensor-card {
@include card-base;
overflow: hidden;
&__header {
@include card-padding(md);
border-bottom: 1px solid $gray-100;
.content {
@include flex-between;
align-items: flex-start;
}
.info {
@include flex-center;
gap: $spacing-md;
.icon-container {
padding: $spacing-sm;
border-radius: $radius-lg;
.icon {
font-size: 1.125rem;
}
}
.details {
h3 {
font-weight: 500;
color: $gray-900;
margin: 0;
}
p {
font-size: 0.875rem;
color: $gray-500;
margin: 0;
}
}
}
.status {
@include flex-center;
gap: $spacing-sm;
.indicator {
@include status-indicator($status-offline);
&--online {
background-color: $status-online;
}
&--offline {
background-color: $status-offline;
}
&--error {
background-color: $status-error;
}
}
.label {
font-size: 0.75rem;
color: $gray-500;
text-transform: capitalize;
}
}
}
&__content {
@include card-padding(md);
.space-y-4 > * + * {
margin-top: $spacing-md;
}
.section-title {
display: block;
font-size: 0.875rem;
font-weight: 500;
color: $gray-700;
margin-bottom: $spacing-sm;
}
}
&__room-select {
width: 100%;
padding: $spacing-md;
border: 1px solid $gray-200;
border-radius: $radius-lg;
background-color: white;
font-size: 0.875rem;
}
&__tags {
display: flex;
flex-wrap: wrap;
gap: $spacing-xs;
margin-bottom: $spacing-sm;
.tag {
padding: $spacing-xs $spacing-sm;
background-color: $gray-100;
color: $gray-700;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
}
&__capabilities {
display: flex;
flex-wrap: wrap;
gap: $spacing-xs;
.capability {
padding: $spacing-xs $spacing-sm;
background-color: #dbeafe;
color: #1e40af;
border-radius: $radius-md;
font-size: 0.75rem;
font-weight: 500;
}
}
&__values-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: $spacing-sm;
font-size: 0.75rem;
.metric {
background-color: $gray-50;
border-radius: $radius-md;
padding: $spacing-sm;
.label {
color: $gray-600;
margin-bottom: $spacing-xs;
}
.value {
font-weight: 500;
color: $gray-900;
.unit {
color: $gray-500;
}
}
}
}
&__device-info {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: $spacing-sm;
font-size: 0.75rem;
color: $gray-600;
.info-item {
.label {
font-weight: 500;
}
.value {
margin-top: $spacing-xs;
}
}
.battery-info {
@include flex-center;
gap: $spacing-xs;
.battery-bar {
@include battery-indicator;
width: 0.75rem;
}
}
.signal-info {
@include flex-center;
gap: $spacing-xs;
.signal-bars {
display: flex;
gap: 1px;
.bar {
width: $spacing-xs;
height: $spacing-sm;
background-color: $gray-200;
border-radius: 1px;
&.active {
background-color: $status-online;
}
}
}
}
}
&__actions-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: $spacing-sm;
.action-btn {
@include flex-center;
gap: $spacing-sm;
padding: $spacing-md;
background-color: $gray-50;
border: 1px solid $gray-200;
border-radius: $radius-lg;
font-size: 0.875rem;
font-weight: 500;
color: $gray-700;
transition: all $transition-fast;
cursor: pointer;
&:hover:not(:disabled) {
background-color: $gray-100;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.text {
@include truncate;
}
}
}
&__no-actions {
.placeholder {
font-size: 0.75rem;
color: $gray-500;
text-align: center;
padding: $spacing-md;
background-color: $gray-50;
border: 2px dashed $gray-200;
border-radius: $radius-md;
}
}
}
// Sensor Type Specific Styles
.sensor-energy {
@include sensor-type-style($sensor-energy-bg, $sensor-energy-text);
}
.sensor-co2 {
@include sensor-type-style($sensor-co2-bg, $sensor-co2-text);
}
.sensor-temperature {
@include sensor-type-style($sensor-temperature-bg, $sensor-temperature-text);
}
.sensor-humidity {
@include sensor-type-style($sensor-humidity-bg, $sensor-humidity-text);
}
.sensor-hvac {
@include sensor-type-style($sensor-hvac-bg, $sensor-hvac-text);
}
.sensor-lighting {
@include sensor-type-style($sensor-lighting-bg, $sensor-lighting-text);
}
.sensor-security {
@include sensor-type-style($sensor-security-bg, $sensor-security-text);
}

View File

@@ -0,0 +1,47 @@
// Form Elements
.form-select {
padding: $spacing-sm $spacing-md;
border: 1px solid $gray-200;
border-radius: $radius-lg;
background-color: white;
font-size: 0.875rem;
transition: border-color $transition-fast;
&:focus {
outline: none;
border-color: $primary;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
}
.form-input {
padding: $spacing-sm $spacing-md;
border: 1px solid $gray-200;
border-radius: $radius-lg;
background-color: white;
font-size: 0.875rem;
transition: border-color $transition-fast;
&:focus {
outline: none;
border-color: $primary;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
&--full-width {
width: 100%;
}
}
.form-label {
display: block;
font-size: 0.875rem;
font-weight: 500;
color: $gray-700;
margin-bottom: $spacing-sm;
}
// Custom Range Input
.range-slider {
@include custom-slider;
}

View File

@@ -0,0 +1,256 @@
// Action Modal Styles
.action-modal {
position: fixed;
inset: 0;
z-index: 50;
@include flex-center;
&__backdrop {
position: absolute;
inset: 0;
background-color: rgba(0, 0, 0, 0.5);
}
&__container {
position: relative;
background-color: white;
border-radius: $radius-2xl;
box-shadow: $shadow-xl;
max-width: 28rem;
width: 100%;
margin: 0 $spacing-md;
max-height: 90vh;
overflow-y: auto;
}
&__header {
padding: $spacing-xl;
border-bottom: 1px solid $gray-100;
@include flex-between;
h3 {
font-size: 1.125rem;
font-weight: 500;
color: $gray-900;
margin: 0;
}
p {
font-size: 0.875rem;
color: $gray-600;
margin: 0;
}
}
&__close-button {
padding: $spacing-sm;
border-radius: 50%;
transition: background-color $transition-fast;
background: none;
border: none;
cursor: pointer;
&:hover {
background-color: $gray-100;
}
svg {
width: 1.25rem;
height: 1.25rem;
color: $gray-400;
}
}
&__content {
padding: $spacing-xl;
.space-y-4 > * + * {
margin-top: $spacing-md;
}
}
&__footer {
padding: $spacing-xl $spacing-xl $spacing-md;
background-color: $gray-50;
border-radius: 0 0 $radius-2xl $radius-2xl;
display: flex;
gap: $spacing-md;
button {
flex: 1;
padding: $spacing-sm $spacing-md;
border-radius: $radius-lg;
font-weight: 500;
transition: all $transition-fast;
&.cancel {
@include button-secondary;
}
&.execute {
@include button-primary;
&:disabled {
background-color: #93c5fd;
cursor: not-allowed;
}
}
}
}
}
// Range Input Styling
.range-input {
&__container {
.space-y-3 > * + * {
margin-top: $spacing-md;
}
}
&__slider {
@include custom-slider;
}
&__labels {
@include flex-between;
font-size: 0.875rem;
color: $gray-600;
.current-value {
font-weight: 500;
}
}
&__label {
display: block;
font-size: 0.875rem;
font-weight: 500;
color: $gray-700;
margin-bottom: $spacing-sm;
}
}
// Option Selection
.option-selection {
&__label {
display: block;
font-size: 0.875rem;
font-weight: 500;
color: $gray-700;
margin-bottom: $spacing-sm;
}
&__grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: $spacing-sm;
}
&__button {
padding: $spacing-md;
border: 1px solid $gray-200;
border-radius: $radius-lg;
font-size: 0.875rem;
font-weight: 500;
transition: all $transition-fast;
cursor: pointer;
background: white;
color: $gray-700;
&:hover {
background-color: $gray-50;
}
&.selected {
background-color: $primary;
color: white;
border-color: $primary;
}
}
}
// Toggle Control
.toggle-control {
@include flex-between;
&__label {
font-size: 0.875rem;
font-weight: 500;
color: $gray-700;
}
&__switch {
position: relative;
display: inline-flex;
height: 1.5rem;
width: 2.75rem;
align-items: center;
border-radius: 9999px;
transition: background-color $transition-fast;
cursor: pointer;
border: none;
&.on {
background-color: $primary;
}
&.off {
background-color: $gray-200;
}
}
&__thumb {
display: inline-block;
height: 1rem;
width: 1rem;
border-radius: 50%;
background-color: white;
transition: transform $transition-fast;
&.on {
transform: translateX(1.5rem);
}
&.off {
transform: translateX(0.25rem);
}
}
&__status {
font-size: 0.875rem;
color: $gray-500;
margin-top: $spacing-xs;
}
}
// Trigger Action
.trigger-action {
&__container {
background-color: $gray-50;
border-radius: $radius-lg;
padding: $spacing-md;
}
&__content {
@include flex-center;
gap: $spacing-md;
.icon {
font-size: 2rem;
}
.info {
.title {
font-weight: 500;
color: $gray-900;
margin: 0;
}
.description {
font-size: 0.875rem;
color: $gray-600;
margin: 0;
}
}
}
}

View File

@@ -0,0 +1,27 @@
// Dashboard Layout
.dashboard {
&__container {
max-width: 1200px;
margin: 0 auto;
padding: $spacing-md;
@include respond-above($breakpoint-sm) {
padding: $spacing-lg;
}
}
&__main {
flex-grow: 1;
padding-bottom: 5rem; // Space for bottom nav on mobile
@include respond-above($breakpoint-md) {
padding-bottom: 0;
}
}
&__content {
.space-y-6 > * + * {
margin-top: $spacing-xl;
}
}
}

View File

@@ -0,0 +1,52 @@
// Grid Layouts
.grid {
display: grid;
&--1 { grid-template-columns: 1fr; }
&--2 { grid-template-columns: repeat(2, 1fr); }
&--3 { grid-template-columns: repeat(3, 1fr); }
&--4 { grid-template-columns: repeat(4, 1fr); }
&--gap-2 { gap: $spacing-sm; }
&--gap-4 { gap: $spacing-md; }
&--gap-6 { gap: $spacing-lg; }
// Responsive grids
&--responsive-simple {
@include grid-responsive(1, 3, 4, $spacing-md);
}
&--responsive-detailed {
@include grid-responsive(1, 2, 3, $spacing-lg);
}
&--responsive-cards {
@include grid-responsive(1, 2, 3, $spacing-md);
}
}
// Flexbox utilities
.flex {
display: flex;
&--center {
@include flex-center;
}
&--between {
@include flex-between;
}
&--column {
@include flex-column;
}
&--wrap {
flex-wrap: wrap;
}
&--gap-1 { gap: $spacing-xs; }
&--gap-2 { gap: $spacing-sm; }
&--gap-3 { gap: $spacing-md; }
&--gap-4 { gap: $spacing-lg; }
}

23
src/assets/scss/main.scss Normal file
View File

@@ -0,0 +1,23 @@
@use 'tailwindcss';
@import 'abstracts/variables';
@import 'abstracts/mixins';
@import 'base/reset';
@import 'base/typography';
@import 'components/buttons';
@import 'components/cards';
@import 'components/forms';
@import 'components/modals';
@import 'layouts/grid';
@import 'layouts/dashboard';
@import 'pages/sensor-management';
@import 'pages/home';
@import 'utilities/helpers';
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,167 @@
// Home Dashboard Page
.home-dashboard {
&__filters {
display: flex;
flex-direction: column;
gap: $spacing-md;
margin-bottom: $spacing-xl;
@include respond-above($breakpoint-sm) {
flex-direction: row;
}
.filter-select {
@extend .form-select;
}
}
&__metrics-row {
display: grid;
grid-template-columns: 1fr;
gap: $spacing-md;
min-height: 24rem;
@include respond-above($breakpoint-lg) {
grid-template-columns: 1fr 1fr;
}
.metrics-grid {
@include grid-responsive(1, 2, 3, $spacing-md);
@include respond-above($breakpoint-lg) {
grid-template-columns: 1fr;
@include respond-above($breakpoint-lg) {
grid-template-columns: repeat(3, 1fr);
}
}
}
.chart-container {
// Chart styling handled by chart library
}
}
&__charts-row {
@include grid-responsive(1, 2, 2, $spacing-md);
}
&__topics-row {
@include grid-responsive(1, 2, 2, $spacing-md);
.topic-card {
@include card-base;
@include card-padding(md);
.title {
font-size: 0.875rem;
font-weight: 700;
color: $gray-500;
margin-bottom: $spacing-sm;
}
}
}
&__leaderboards-row {
@include grid-responsive(1, 2, 2, $spacing-md);
.leaderboard-card {
@include card-base;
@include card-padding(md);
.title {
font-size: 0.875rem;
font-weight: 700;
color: $gray-500;
margin-bottom: $spacing-sm;
}
}
}
}
// Metric Cards
.metric-card {
@include card-base;
@include card-padding(md);
@include flex-column;
justify-content: space-between;
aspect-ratio: 1;
.title {
font-size: 0.875rem;
font-weight: 700;
color: $gray-500;
}
.content-section {
flex-grow: 1;
@include flex-center;
justify-content: flex-start;
.value {
color: $gray-900;
font-weight: 700;
font-size: 1.5rem;
.unit {
font-size: 0.875rem;
color: $gray-500;
}
}
}
}
// Graph Metric Cards
.graph-metric-card {
@include card-base;
@include card-padding(md);
.header {
@include flex-between;
margin-bottom: $spacing-md;
.title {
font-size: 0.875rem;
font-weight: 700;
color: $gray-500;
}
.trend-indicator {
font-size: 0.75rem;
padding: $spacing-xs $spacing-sm;
border-radius: $radius-md;
&--up {
background-color: #dcfce7;
color: #166534;
}
&--down {
background-color: #fee2e2;
color: #991b1b;
}
&--neutral {
background-color: $gray-100;
color: $gray-600;
}
}
}
.value {
font-size: 1.25rem;
font-weight: 700;
color: $gray-900;
margin-bottom: $spacing-sm;
.unit {
font-size: 0.875rem;
color: $gray-500;
}
}
.chart {
height: 2rem;
// Chart styling handled by chart library
}
}

View File

@@ -0,0 +1,114 @@
// Sensor Management Page
.sensor-management {
&__header {
@include flex-between;
align-items: flex-start;
flex-direction: column;
@include respond-above($breakpoint-sm) {
align-items: center;
flex-direction: row;
}
.title-section {
h1 {
font-size: 1.5rem;
font-weight: 700;
color: $gray-900;
margin-bottom: $spacing-xs;
}
p {
color: $gray-600;
}
}
.status-section {
margin-top: $spacing-md;
@include respond-above($breakpoint-sm) {
margin-top: 0;
}
.status-info {
@include flex-center;
gap: $spacing-sm;
font-size: 0.875rem;
color: $gray-600;
.connection-indicator {
@include status-indicator($status-offline);
&--connected {
background-color: $status-online;
}
&--disconnected {
background-color: $status-error;
}
}
.separator {
margin: 0 $spacing-sm;
}
}
}
}
&__filters {
display: flex;
flex-direction: column;
gap: $spacing-md;
@include respond-above($breakpoint-lg) {
flex-direction: row;
}
.filter-group {
display: flex;
flex-direction: column;
gap: $spacing-md;
flex: 1;
@include respond-above($breakpoint-sm) {
flex-direction: row;
}
}
.view-toggle {
@extend .toggle-group;
}
}
&__grid {
&--simple {
@include grid-responsive(1, 3, 4, $spacing-md);
}
&--detailed {
@include grid-responsive(1, 2, 3, $spacing-lg);
}
}
&__empty-state {
text-align: center;
padding: $spacing-2xl * 2;
.icon {
color: $gray-400;
font-size: 3.75rem;
margin-bottom: $spacing-md;
}
.title {
font-size: 1.125rem;
font-weight: 500;
color: $gray-900;
margin-bottom: $spacing-sm;
}
.description {
color: $gray-600;
}
}
}

View File

@@ -0,0 +1,109 @@
// Utility Classes
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
// Spacing utilities
.space-y-2 > * + * { margin-top: $spacing-sm; }
.space-y-3 > * + * { margin-top: $spacing-md; }
.space-y-4 > * + * { margin-top: $spacing-lg; }
.space-y-6 > * + * { margin-top: $spacing-xl; }
.space-x-2 > * + * { margin-left: $spacing-sm; }
.space-x-3 > * + * { margin-left: $spacing-md; }
.space-x-4 > * + * { margin-left: $spacing-lg; }
// Margin utilities
.m-0 { margin: 0; }
.mb-1 { margin-bottom: $spacing-xs; }
.mb-2 { margin-bottom: $spacing-sm; }
.mb-3 { margin-bottom: $spacing-md; }
.mb-4 { margin-bottom: $spacing-lg; }
.mt-1 { margin-top: $spacing-xs; }
.mt-2 { margin-top: $spacing-sm; }
.mt-3 { margin-top: $spacing-md; }
.mt-4 { margin-top: $spacing-lg; }
// Padding utilities
.p-0 { padding: 0; }
.p-1 { padding: $spacing-xs; }
.p-2 { padding: $spacing-sm; }
.p-3 { padding: $spacing-md; }
.p-4 { padding: $spacing-lg; }
// Width utilities
.w-full { width: 100%; }
.w-auto { width: auto; }
// Height utilities
.h-full { height: 100%; }
.h-auto { height: auto; }
// Color utilities
.text-primary { color: $primary; }
.text-secondary { color: $secondary; }
.text-success { color: $success; }
.text-warning { color: $warning; }
.text-danger { color: $danger; }
.text-gray-400 { color: $gray-400; }
.text-gray-500 { color: $gray-500; }
.text-gray-600 { color: $gray-600; }
.text-gray-700 { color: $gray-700; }
.text-gray-900 { color: $gray-900; }
// Background utilities
.bg-primary { background-color: $primary; }
.bg-white { background-color: white; }
.bg-gray-50 { background-color: $gray-50; }
.bg-gray-100 { background-color: $gray-100; }
// Border utilities
.border { border: 1px solid $gray-200; }
.border-0 { border: 0; }
.border-gray-100 { border-color: $gray-100; }
.border-gray-200 { border-color: $gray-200; }
// Border radius utilities
.rounded { border-radius: $radius-md; }
.rounded-lg { border-radius: $radius-lg; }
.rounded-xl { border-radius: $radius-xl; }
.rounded-2xl { border-radius: $radius-2xl; }
.rounded-full { border-radius: 9999px; }
// Shadow utilities
.shadow-sm { box-shadow: $shadow-sm; }
.shadow-md { box-shadow: $shadow-md; }
.shadow-lg { box-shadow: $shadow-lg; }
.shadow-xl { box-shadow: $shadow-xl; }
// Position utilities
.relative { position: relative; }
.absolute { position: absolute; }
.fixed { position: fixed; }
// Z-index utilities
.z-10 { z-index: 10; }
.z-20 { z-index: 20; }
.z-50 { z-index: 50; }
// Overflow utilities
.overflow-hidden { overflow: hidden; }
.overflow-y-auto { overflow-y: auto; }
// Cursor utilities
.cursor-pointer { cursor: pointer; }
.cursor-not-allowed { cursor: not-allowed; }
// Opacity utilities
.opacity-50 { opacity: 0.5; }
.opacity-75 { opacity: 0.75; }