feat: add stylelint for SCSS and CSS, update theme and global styles

- Added stylelint scripts to package.json for linting SCSS and CSS files.
- Updated global styles to remove quotes from font-family declarations and changed `currentColor` to `currentcolor`.
- Refactored theme.scss to use shorthand hex color codes and updated font-family declarations.
- Modified carousel component to remove unnecessary onSelect call.
- Enhanced useSnippetForm hook with comments and ESLint disable/enable for clarity.
- Improved mixins in _mixins.scss for flexbox and responsive breakpoints.
- Updated color definitions in _variables.scss to use the `hsl()` format with degrees.
- Changed button and dialog styles to use `currentcolor` for background.
- Adjusted header styles for box-shadow and gradient backgrounds.
- Refined typography styles to ensure consistent font-family usage.
- Enhanced utility classes in _utilities.scss for better readability and maintainability.
This commit is contained in:
2026-01-20 00:06:44 +00:00
parent f25e5e0597
commit 9ae6776f37
16 changed files with 1738 additions and 216 deletions

5
.stylelintignore Normal file
View File

@@ -0,0 +1,5 @@
.next
node_modules
dist
coverage
**/generated/**

4
.stylelintrc.json Normal file
View File

@@ -0,0 +1,4 @@
{
"extends": ["stylelint-config-standard-scss"],
"rules": {}
}

View File

@@ -18,8 +18,6 @@ export default [
}, },
rules: { rules: {
...reactHooks.configs.recommended.rules, ...reactHooks.configs.recommended.rules,
'react-hooks/set-state-in-effect': 'off',
'react-hooks/purity': 'off',
}, },
}, },
{ {

1341
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "eslint .", "lint": "eslint .",
"stylelint": "stylelint \"src/**/*.{scss,css}\"",
"kill": "fuser -k 5000/tcp" "kill": "fuser -k 5000/tcp"
}, },
"dependencies": { "dependencies": {
@@ -74,6 +75,9 @@
"eslint-config-next": "^16.1.3", "eslint-config-next": "^16.1.3",
"eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-hooks": "^7.0.1",
"globals": "^16.0.0", "globals": "^16.0.0",
"stylelint": "^17.0.0",
"stylelint-config-standard-scss": "^17.0.0",
"stylelint-scss": "^7.0.0",
"typescript": "~5.9.3", "typescript": "~5.9.3",
"typescript-eslint": "^8.53.1" "typescript-eslint": "^8.53.1"
}, },

View File

@@ -1,7 +1,7 @@
@use '../styles/abstracts' as *; @use '../styles/abstracts' as *;
@use '../styles/utilities/utilities'; @use '../styles/utilities/utilities';
@use '../styles/components'; @use '../styles/components';
@use './theme.scss'; @use './theme';
// Global resets // Global resets
* { * {
@@ -23,7 +23,7 @@
body { body {
background: $background; background: $background;
color: $foreground; color: $foreground;
font-family: var(--font-inter), 'Inter', 'Roboto', system-ui, sans-serif; font-family: var(--font-inter), Inter, Roboto, system-ui, sans-serif;
font-size: $font-body-medium; font-size: $font-body-medium;
line-height: $line-height-body-medium; line-height: $line-height-body-medium;
letter-spacing: $letter-spacing-body; letter-spacing: $letter-spacing-body;
@@ -150,7 +150,7 @@ body {
// Typography base for headings // Typography base for headings
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
font-family: var(--font-inter), 'Inter', 'Roboto', system-ui, sans-serif; font-family: var(--font-inter), Inter, Roboto, system-ui, sans-serif;
font-weight: 400; font-weight: 400;
letter-spacing: $letter-spacing-headline; letter-spacing: $letter-spacing-headline;
} }
@@ -409,7 +409,7 @@ code, pre {
content: ''; content: '';
position: absolute; position: absolute;
inset: 0; inset: 0;
background-color: currentColor; background-color: currentcolor;
opacity: 0; opacity: 0;
transition: opacity $duration-short-4 $easing-standard; transition: opacity $duration-short-4 $easing-standard;
pointer-events: none; pointer-events: none;
@@ -438,6 +438,7 @@ code, pre {
transform: scale(0); transform: scale(0);
opacity: 0.12; opacity: 0.12;
} }
to { to {
transform: scale(4); transform: scale(4);
opacity: 0; opacity: 0;
@@ -456,7 +457,7 @@ code, pre {
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%) scale(0); transform: translate(-50%, -50%) scale(0);
background: radial-gradient(circle, currentColor 10%, transparent 10.01%); background: radial-gradient(circle, currentcolor 10%, transparent 10.01%);
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
border-radius: 50%; border-radius: 50%;
@@ -476,6 +477,7 @@ code, pre {
height: 0; height: 0;
opacity: 0; opacity: 0;
} }
to { to {
height: var(--radix-accordion-content-height); height: var(--radix-accordion-content-height);
opacity: 1; opacity: 1;
@@ -487,6 +489,7 @@ code, pre {
height: var(--radix-accordion-content-height); height: var(--radix-accordion-content-height);
opacity: 1; opacity: 1;
} }
to { to {
height: 0; height: 0;
opacity: 0; opacity: 0;
@@ -497,6 +500,7 @@ code, pre {
from { from {
opacity: 0; opacity: 0;
} }
to { to {
opacity: 1; opacity: 1;
} }
@@ -506,6 +510,7 @@ code, pre {
from { from {
opacity: 1; opacity: 1;
} }
to { to {
opacity: 0; opacity: 0;
} }
@@ -516,6 +521,7 @@ code, pre {
opacity: 0; opacity: 0;
transform: scale(0.8); transform: scale(0.8);
} }
to { to {
opacity: 1; opacity: 1;
transform: scale(1); transform: scale(1);
@@ -527,6 +533,7 @@ code, pre {
opacity: 0; opacity: 0;
transform: translateY(100%); transform: translateY(100%);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
@@ -538,6 +545,7 @@ code, pre {
opacity: 0; opacity: 0;
transform: translateX(100%); transform: translateX(100%);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateX(0); transform: translateX(0);

View File

@@ -25,22 +25,22 @@
--color-fg-secondary: var(--color-neutral-11); --color-fg-secondary: var(--color-neutral-11);
// Background colors // Background colors
--color-bg: #ffffff; --color-bg: #fff;
--color-bg-inset: var(--color-neutral-2); --color-bg-inset: var(--color-neutral-2);
--color-bg-overlay: #ffffff; --color-bg-overlay: #fff;
// Focus ring // Focus ring
--color-focus-ring: var(--color-accent-9); --color-focus-ring: var(--color-accent-9);
// Fonts // Fonts
--font-sans-serif: ui-sans-serif, system-ui, sans-serif; --font-sans-serif: ui-sans-serif, system-ui, sans-serif;
--font-serif: ui-serif, Georgia, serif; --font-serif: ui-serif, georgia, serif;
--font-monospace: ui-monospace, 'SF Mono', Monaco, Consolas, monospace; --font-monospace: ui-monospace, 'SF Mono', monaco, consolas, monospace;
--font-family: var(--font-sans-serif); --font-family: var(--font-sans-serif);
} }
#spark-app.dark-theme { #spark-app.dark-theme {
--color-bg: var(--color-neutral-1); --color-bg: var(--color-neutral-1);
--color-bg-inset: #000000; --color-bg-inset: #000;
--color-bg-overlay: var(--color-neutral-3); --color-bg-overlay: var(--color-neutral-3);
} }

View File

@@ -96,7 +96,6 @@ function Carousel({
useEffect(() => { useEffect(() => {
if (!api) return if (!api) return
onSelect(api)
api.on("reInit", onSelect) api.on("reInit", onSelect)
api.on("select", onSelect) api.on("select", onSelect)

View File

@@ -12,6 +12,9 @@ export function useSnippetForm(editingSnippet?: Snippet | null, open?: boolean)
const [inputParameters, setInputParameters] = useState<InputParameter[]>([]) const [inputParameters, setInputParameters] = useState<InputParameter[]>([])
const [errors, setErrors] = useState<{ title?: string; code?: string }>({}) const [errors, setErrors] = useState<{ title?: string; code?: string }>({})
/* eslint-disable react-hooks/set-state-in-effect */
// This effect hydrates the form when the dialog opens or when a different snippet is selected for editing.
// The state reset is intentional user-facing behavior.
useEffect(() => { useEffect(() => {
if (editingSnippet) { if (editingSnippet) {
setTitle(editingSnippet.title) setTitle(editingSnippet.title)
@@ -32,6 +35,7 @@ export function useSnippetForm(editingSnippet?: Snippet | null, open?: boolean)
} }
setErrors({}) setErrors({})
}, [editingSnippet, open]) }, [editingSnippet, open])
/* eslint-enable react-hooks/set-state-in-effect */
const handleAddParameter = () => { const handleAddParameter = () => {
setInputParameters((prev) => [ setInputParameters((prev) => [

View File

@@ -4,10 +4,9 @@
// Flexbox mixins // Flexbox mixins
@mixin flex($direction: row, $justify: flex-start, $align: stretch, $wrap: nowrap) { @mixin flex($direction: row, $justify: flex-start, $align: stretch, $wrap: nowrap) {
display: flex; display: flex;
flex-direction: $direction; flex-flow: $direction $wrap;
justify-content: $justify; justify-content: $justify;
align-items: $align; align-items: $align;
flex-wrap: $wrap;
} }
@mixin flex-center { @mixin flex-center {
@@ -112,6 +111,7 @@
// Responsive breakpoint mixin // Responsive breakpoint mixin
@mixin respond-to($breakpoint) { @mixin respond-to($breakpoint) {
$size: fn.breakpoint($breakpoint); $size: fn.breakpoint($breakpoint);
@media (min-width: $size) { @media (min-width: $size) {
@content; @content;
} }
@@ -124,6 +124,7 @@
@include rounded(md); @include rounded(md);
@include font(medium); @include font(medium);
@include text(sm); @include text(sm);
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -144,25 +145,26 @@
background: vars.$card; background: vars.$card;
color: vars.$card-foreground; color: vars.$card-foreground;
border: 1px solid vars.$border; border: 1px solid vars.$border;
@include rounded(lg); @include rounded(lg);
@include p(6); @include p(6);
} }
// Shadow mixins // Shadow mixins
@mixin shadow-sm { @mixin shadow-sm {
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); box-shadow: 0 1px 2px 0 rgb(0 0 0 / 5%);
} }
@mixin shadow { @mixin shadow {
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); box-shadow: 0 1px 3px 0 rgb(0 0 0 / 10%), 0 1px 2px -1px rgb(0 0 0 / 10%);
} }
@mixin shadow-md { @mixin shadow-md {
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); box-shadow: 0 4px 6px -1px rgb(0 0 0 / 10%), 0 2px 4px -2px rgb(0 0 0 / 10%);
} }
@mixin shadow-lg { @mixin shadow-lg {
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); box-shadow: 0 10px 15px -3px rgb(0 0 0 / 10%), 0 4px 6px -4px rgb(0 0 0 / 10%);
} }
// Transition mixin // Transition mixin
@@ -185,7 +187,7 @@
padding: 0; padding: 0;
margin: -1px; margin: -1px;
overflow: hidden; overflow: hidden;
clip: rect(0, 0, 0, 0); clip-path: inset(50%);
white-space: nowrap; white-space: nowrap;
border-width: 0; border-width: 0;
} }
@@ -200,10 +202,7 @@
@mixin absolute-fill { @mixin absolute-fill {
position: absolute; position: absolute;
top: 0; inset: 0;
right: 0;
bottom: 0;
left: 0;
} }
// Focus ring // Focus ring

View File

@@ -5,129 +5,129 @@
// === MD3 Primary Tonal Palette === // === MD3 Primary Tonal Palette ===
// Purple/Violet primary color with full tonal range // Purple/Violet primary color with full tonal range
$md3-primary-0: hsl(260, 50%, 0%); $md3-primary-0: hsl(260deg 50% 0%);
$md3-primary-10: hsl(260, 50%, 10%); $md3-primary-10: hsl(260deg 50% 10%);
$md3-primary-20: hsl(260, 50%, 20%); $md3-primary-20: hsl(260deg 50% 20%);
$md3-primary-25: hsl(260, 50%, 25%); $md3-primary-25: hsl(260deg 50% 25%);
$md3-primary-30: hsl(260, 50%, 30%); $md3-primary-30: hsl(260deg 50% 30%);
$md3-primary-35: hsl(260, 50%, 35%); $md3-primary-35: hsl(260deg 50% 35%);
$md3-primary-40: hsl(260, 50%, 40%); $md3-primary-40: hsl(260deg 50% 40%);
$md3-primary-50: hsl(260, 50%, 50%); $md3-primary-50: hsl(260deg 50% 50%);
$md3-primary-60: hsl(260, 50%, 60%); $md3-primary-60: hsl(260deg 50% 60%);
$md3-primary-70: hsl(260, 50%, 70%); $md3-primary-70: hsl(260deg 50% 70%);
$md3-primary-80: hsl(260, 50%, 80%); $md3-primary-80: hsl(260deg 50% 80%);
$md3-primary-90: hsl(260, 50%, 90%); $md3-primary-90: hsl(260deg 50% 90%);
$md3-primary-95: hsl(260, 50%, 95%); $md3-primary-95: hsl(260deg 50% 95%);
$md3-primary-99: hsl(260, 50%, 99%); $md3-primary-99: hsl(260deg 50% 99%);
$md3-primary-100: hsl(260, 50%, 100%); $md3-primary-100: hsl(260deg 50% 100%);
// === MD3 Secondary Tonal Palette === // === MD3 Secondary Tonal Palette ===
// Desaturated purple for secondary elements // Desaturated purple for secondary elements
$md3-secondary-0: hsl(260, 15%, 0%); $md3-secondary-0: hsl(260deg 15% 0%);
$md3-secondary-10: hsl(260, 15%, 10%); $md3-secondary-10: hsl(260deg 15% 10%);
$md3-secondary-20: hsl(260, 15%, 20%); $md3-secondary-20: hsl(260deg 15% 20%);
$md3-secondary-25: hsl(260, 15%, 25%); $md3-secondary-25: hsl(260deg 15% 25%);
$md3-secondary-30: hsl(260, 15%, 30%); $md3-secondary-30: hsl(260deg 15% 30%);
$md3-secondary-35: hsl(260, 15%, 35%); $md3-secondary-35: hsl(260deg 15% 35%);
$md3-secondary-40: hsl(260, 15%, 40%); $md3-secondary-40: hsl(260deg 15% 40%);
$md3-secondary-50: hsl(260, 15%, 50%); $md3-secondary-50: hsl(260deg 15% 50%);
$md3-secondary-60: hsl(260, 15%, 60%); $md3-secondary-60: hsl(260deg 15% 60%);
$md3-secondary-70: hsl(260, 15%, 70%); $md3-secondary-70: hsl(260deg 15% 70%);
$md3-secondary-80: hsl(260, 15%, 80%); $md3-secondary-80: hsl(260deg 15% 80%);
$md3-secondary-90: hsl(260, 15%, 90%); $md3-secondary-90: hsl(260deg 15% 90%);
$md3-secondary-95: hsl(260, 15%, 95%); $md3-secondary-95: hsl(260deg 15% 95%);
$md3-secondary-99: hsl(260, 15%, 99%); $md3-secondary-99: hsl(260deg 15% 99%);
$md3-secondary-100: hsl(260, 15%, 100%); $md3-secondary-100: hsl(260deg 15% 100%);
// === MD3 Tertiary Tonal Palette === // === MD3 Tertiary Tonal Palette ===
// Cyan/Teal for tertiary accents // Cyan/Teal for tertiary accents
$md3-tertiary-0: hsl(180, 50%, 0%); $md3-tertiary-0: hsl(180deg 50% 0%);
$md3-tertiary-10: hsl(180, 50%, 10%); $md3-tertiary-10: hsl(180deg 50% 10%);
$md3-tertiary-20: hsl(180, 50%, 20%); $md3-tertiary-20: hsl(180deg 50% 20%);
$md3-tertiary-25: hsl(180, 50%, 25%); $md3-tertiary-25: hsl(180deg 50% 25%);
$md3-tertiary-30: hsl(180, 50%, 30%); $md3-tertiary-30: hsl(180deg 50% 30%);
$md3-tertiary-35: hsl(180, 50%, 35%); $md3-tertiary-35: hsl(180deg 50% 35%);
$md3-tertiary-40: hsl(180, 50%, 40%); $md3-tertiary-40: hsl(180deg 50% 40%);
$md3-tertiary-50: hsl(180, 50%, 50%); $md3-tertiary-50: hsl(180deg 50% 50%);
$md3-tertiary-60: hsl(180, 50%, 60%); $md3-tertiary-60: hsl(180deg 50% 60%);
$md3-tertiary-70: hsl(180, 50%, 70%); $md3-tertiary-70: hsl(180deg 50% 70%);
$md3-tertiary-80: hsl(180, 50%, 80%); $md3-tertiary-80: hsl(180deg 50% 80%);
$md3-tertiary-90: hsl(180, 50%, 90%); $md3-tertiary-90: hsl(180deg 50% 90%);
$md3-tertiary-95: hsl(180, 50%, 95%); $md3-tertiary-95: hsl(180deg 50% 95%);
$md3-tertiary-99: hsl(180, 50%, 99%); $md3-tertiary-99: hsl(180deg 50% 99%);
$md3-tertiary-100: hsl(180, 50%, 100%); $md3-tertiary-100: hsl(180deg 50% 100%);
// === MD3 Error Tonal Palette === // === MD3 Error Tonal Palette ===
$md3-error-0: hsl(0, 75%, 0%); $md3-error-0: hsl(0deg 75% 0%);
$md3-error-10: hsl(0, 75%, 10%); $md3-error-10: hsl(0deg 75% 10%);
$md3-error-20: hsl(0, 75%, 20%); $md3-error-20: hsl(0deg 75% 20%);
$md3-error-30: hsl(0, 75%, 30%); $md3-error-30: hsl(0deg 75% 30%);
$md3-error-40: hsl(0, 75%, 40%); $md3-error-40: hsl(0deg 75% 40%);
$md3-error-50: hsl(0, 75%, 50%); $md3-error-50: hsl(0deg 75% 50%);
$md3-error-60: hsl(0, 75%, 60%); $md3-error-60: hsl(0deg 75% 60%);
$md3-error-70: hsl(0, 75%, 70%); $md3-error-70: hsl(0deg 75% 70%);
$md3-error-80: hsl(0, 75%, 80%); $md3-error-80: hsl(0deg 75% 80%);
$md3-error-90: hsl(0, 75%, 90%); $md3-error-90: hsl(0deg 75% 90%);
$md3-error-95: hsl(0, 75%, 95%); $md3-error-95: hsl(0deg 75% 95%);
$md3-error-100: hsl(0, 75%, 100%); $md3-error-100: hsl(0deg 75% 100%);
// === MD3 Neutral Tonal Palette === // === MD3 Neutral Tonal Palette ===
// For surfaces and backgrounds // For surfaces and backgrounds
$md3-neutral-0: hsl(260, 10%, 0%); $md3-neutral-0: hsl(260deg 10% 0%);
$md3-neutral-4: hsl(260, 10%, 4%); $md3-neutral-4: hsl(260deg 10% 4%);
$md3-neutral-6: hsl(260, 10%, 6%); $md3-neutral-6: hsl(260deg 10% 6%);
$md3-neutral-10: hsl(260, 10%, 10%); $md3-neutral-10: hsl(260deg 10% 10%);
$md3-neutral-12: hsl(260, 10%, 12%); $md3-neutral-12: hsl(260deg 10% 12%);
$md3-neutral-17: hsl(260, 10%, 17%); $md3-neutral-17: hsl(260deg 10% 17%);
$md3-neutral-20: hsl(260, 10%, 20%); $md3-neutral-20: hsl(260deg 10% 20%);
$md3-neutral-22: hsl(260, 10%, 22%); $md3-neutral-22: hsl(260deg 10% 22%);
$md3-neutral-24: hsl(260, 10%, 24%); $md3-neutral-24: hsl(260deg 10% 24%);
$md3-neutral-25: hsl(260, 10%, 25%); $md3-neutral-25: hsl(260deg 10% 25%);
$md3-neutral-30: hsl(260, 10%, 30%); $md3-neutral-30: hsl(260deg 10% 30%);
$md3-neutral-35: hsl(260, 10%, 35%); $md3-neutral-35: hsl(260deg 10% 35%);
$md3-neutral-40: hsl(260, 10%, 40%); $md3-neutral-40: hsl(260deg 10% 40%);
$md3-neutral-50: hsl(260, 10%, 50%); $md3-neutral-50: hsl(260deg 10% 50%);
$md3-neutral-60: hsl(260, 10%, 60%); $md3-neutral-60: hsl(260deg 10% 60%);
$md3-neutral-70: hsl(260, 10%, 70%); $md3-neutral-70: hsl(260deg 10% 70%);
$md3-neutral-80: hsl(260, 10%, 80%); $md3-neutral-80: hsl(260deg 10% 80%);
$md3-neutral-87: hsl(260, 10%, 87%); $md3-neutral-87: hsl(260deg 10% 87%);
$md3-neutral-90: hsl(260, 10%, 90%); $md3-neutral-90: hsl(260deg 10% 90%);
$md3-neutral-92: hsl(260, 10%, 92%); $md3-neutral-92: hsl(260deg 10% 92%);
$md3-neutral-94: hsl(260, 10%, 94%); $md3-neutral-94: hsl(260deg 10% 94%);
$md3-neutral-95: hsl(260, 10%, 95%); $md3-neutral-95: hsl(260deg 10% 95%);
$md3-neutral-96: hsl(260, 10%, 96%); $md3-neutral-96: hsl(260deg 10% 96%);
$md3-neutral-98: hsl(260, 10%, 98%); $md3-neutral-98: hsl(260deg 10% 98%);
$md3-neutral-99: hsl(260, 10%, 99%); $md3-neutral-99: hsl(260deg 10% 99%);
$md3-neutral-100: hsl(260, 10%, 100%); $md3-neutral-100: hsl(260deg 10% 100%);
// === MD3 Neutral Variant Tonal Palette === // === MD3 Neutral Variant Tonal Palette ===
// For outline and surface variants // For outline and surface variants
$md3-neutral-variant-0: hsl(260, 15%, 0%); $md3-neutral-variant-0: hsl(260deg 15% 0%);
$md3-neutral-variant-10: hsl(260, 15%, 10%); $md3-neutral-variant-10: hsl(260deg 15% 10%);
$md3-neutral-variant-20: hsl(260, 15%, 20%); $md3-neutral-variant-20: hsl(260deg 15% 20%);
$md3-neutral-variant-25: hsl(260, 15%, 25%); $md3-neutral-variant-25: hsl(260deg 15% 25%);
$md3-neutral-variant-30: hsl(260, 15%, 30%); $md3-neutral-variant-30: hsl(260deg 15% 30%);
$md3-neutral-variant-35: hsl(260, 15%, 35%); $md3-neutral-variant-35: hsl(260deg 15% 35%);
$md3-neutral-variant-40: hsl(260, 15%, 40%); $md3-neutral-variant-40: hsl(260deg 15% 40%);
$md3-neutral-variant-50: hsl(260, 15%, 50%); $md3-neutral-variant-50: hsl(260deg 15% 50%);
$md3-neutral-variant-60: hsl(260, 15%, 60%); $md3-neutral-variant-60: hsl(260deg 15% 60%);
$md3-neutral-variant-70: hsl(260, 15%, 70%); $md3-neutral-variant-70: hsl(260deg 15% 70%);
$md3-neutral-variant-80: hsl(260, 15%, 80%); $md3-neutral-variant-80: hsl(260deg 15% 80%);
$md3-neutral-variant-90: hsl(260, 15%, 90%); $md3-neutral-variant-90: hsl(260deg 15% 90%);
$md3-neutral-variant-95: hsl(260, 15%, 95%); $md3-neutral-variant-95: hsl(260deg 15% 95%);
$md3-neutral-variant-99: hsl(260, 15%, 99%); $md3-neutral-variant-99: hsl(260deg 15% 99%);
$md3-neutral-variant-100: hsl(260, 15%, 100%); $md3-neutral-variant-100: hsl(260deg 15% 100%);
// === MD3 Semantic Colors (Success, Warning, Info) === // === MD3 Semantic Colors (Success, Warning, Info) ===
$md3-success-40: hsl(145, 60%, 35%); $md3-success-40: hsl(145deg 60% 35%);
$md3-success-80: hsl(145, 60%, 75%); $md3-success-80: hsl(145deg 60% 75%);
$md3-success-90: hsl(145, 60%, 90%); $md3-success-90: hsl(145deg 60% 90%);
$md3-warning-40: hsl(40, 80%, 45%); $md3-warning-40: hsl(40deg 80% 45%);
$md3-warning-80: hsl(40, 80%, 75%); $md3-warning-80: hsl(40deg 80% 75%);
$md3-warning-90: hsl(40, 80%, 90%); $md3-warning-90: hsl(40deg 80% 90%);
$md3-info-40: hsl(210, 70%, 45%); $md3-info-40: hsl(210deg 70% 45%);
$md3-info-80: hsl(210, 70%, 75%); $md3-info-80: hsl(210deg 70% 75%);
$md3-info-90: hsl(210, 70%, 90%); $md3-info-90: hsl(210deg 70% 90%);
// ============================================ // ============================================
// MD3 Dark Theme Color Scheme // MD3 Dark Theme Color Scheme
@@ -165,7 +165,6 @@ $on-error-container: $md3-error-90;
$background: $md3-neutral-6; $background: $md3-neutral-6;
$foreground: $md3-neutral-90; $foreground: $md3-neutral-90;
$on-background: $md3-neutral-90; $on-background: $md3-neutral-90;
$surface: $md3-neutral-6; $surface: $md3-neutral-6;
$on-surface: $md3-neutral-90; $on-surface: $md3-neutral-90;
$surface-dim: $md3-neutral-6; $surface-dim: $md3-neutral-6;
@@ -272,7 +271,6 @@ $letter-spacing-label: 0.1px;
// ============================================ // ============================================
$radius-factor: 1; $radius-factor: 1;
$size-scale: 1; $size-scale: 1;
$radius-none: 0; $radius-none: 0;
$radius-extra-small: calc(4px * $radius-factor); // MD3 extra-small $radius-extra-small: calc(4px * $radius-factor); // MD3 extra-small
$radius-small: calc(8px * $radius-factor); // MD3 small $radius-small: calc(8px * $radius-factor); // MD3 small
@@ -348,9 +346,12 @@ $easing-legacy: cubic-bezier(0.4, 0, 0.2, 1);
$size-0: 0px; $size-0: 0px;
$size-px: 1px; $size-px: 1px;
$size-0-5: calc(0.125rem * $size-scale); // 2px $size-0-5: calc(0.125rem * $size-scale); // 2px
$size-1-5: calc(0.375rem * $size-scale); // 6px
$size-1: calc(0.25rem * $size-scale); // 4px $size-1: calc(0.25rem * $size-scale); // 4px
$size-2: calc(0.5rem * $size-scale); // 8px $size-2: calc(0.5rem * $size-scale); // 8px
$size-2-5: calc(0.625rem * $size-scale); // 10px
$size-3: calc(0.75rem * $size-scale); // 12px $size-3: calc(0.75rem * $size-scale); // 12px
$size-3-5: calc(0.875rem * $size-scale); // 14px
$size-4: calc(1rem * $size-scale); // 16px $size-4: calc(1rem * $size-scale); // 16px
$size-5: calc(1.25rem * $size-scale); // 20px $size-5: calc(1.25rem * $size-scale); // 20px
$size-6: calc(1.5rem * $size-scale); // 24px $size-6: calc(1.5rem * $size-scale); // 24px

View File

@@ -37,7 +37,7 @@
position: absolute; position: absolute;
inset: 0; inset: 0;
border-radius: inherit; border-radius: inherit;
background-color: currentColor; background-color: currentcolor;
opacity: 0; opacity: 0;
transition: opacity $duration-short-4 $easing-standard; transition: opacity $duration-short-4 $easing-standard;
pointer-events: none; pointer-events: none;
@@ -253,7 +253,7 @@
position: absolute; position: absolute;
inset: 0; inset: 0;
border-radius: inherit; border-radius: inherit;
background-color: currentColor; background-color: currentcolor;
opacity: 0; opacity: 0;
transition: opacity $duration-short-4 $easing-standard; transition: opacity $duration-short-4 $easing-standard;
pointer-events: none; pointer-events: none;
@@ -330,7 +330,7 @@
position: absolute; position: absolute;
inset: 0; inset: 0;
border-radius: inherit; border-radius: inherit;
background-color: currentColor; background-color: currentcolor;
opacity: 0; opacity: 0;
transition: opacity $duration-short-4 $easing-standard; transition: opacity $duration-short-4 $easing-standard;
pointer-events: none; pointer-events: none;

View File

@@ -421,6 +421,7 @@
from { from {
opacity: 0; opacity: 0;
} }
to { to {
opacity: 1; opacity: 1;
} }
@@ -431,6 +432,7 @@
opacity: 0; opacity: 0;
transform: translate(-50%, -48%) scale(0.95); transform: translate(-50%, -48%) scale(0.95);
} }
to { to {
opacity: 1; opacity: 1;
transform: translate(-50%, -50%) scale(1); transform: translate(-50%, -50%) scale(1);
@@ -442,6 +444,7 @@
opacity: 0; opacity: 0;
transform: scale(0.95); transform: scale(0.95);
} }
to { to {
opacity: 1; opacity: 1;
transform: scale(1); transform: scale(1);
@@ -453,6 +456,7 @@
opacity: 0; opacity: 0;
transform: translateY(100%); transform: translateY(100%);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);

View File

@@ -8,7 +8,7 @@ header {
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 20; z-index: 20;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); // MD3 elevation-1 box-shadow: 0 1px 2px rgb(0 0 0 / 8%); // MD3 elevation-1
.container { .container {
padding: 1rem 1.5rem; padding: 1rem 1.5rem;
@@ -54,6 +54,7 @@ header {
outline-offset: 2px; outline-offset: 2px;
} }
} }
// Logo styling - Material Design 3 inspired // Logo styling - Material Design 3 inspired
.logo-container { .logo-container {
display: flex; display: flex;
@@ -65,13 +66,13 @@ header {
width: 2.5rem; width: 2.5rem;
height: 2.5rem; height: 2.5rem;
border-radius: $radius-xl; // MD3 large shape border-radius: $radius-xl; // MD3 large shape
background: linear-gradient(135deg, $primary 0%, hsl(260, 45%, 50%) 100%); background: linear-gradient(135deg, $primary 0%, hsl(260deg 45% 50%) 100%);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: box-shadow:
0 1px 2px rgba(0, 0, 0, 0.12), // MD3 elevation-1 0 1px 2px rgb(0 0 0 / 12%), // MD3 elevation-1
0 1px 3px rgba(0, 0, 0, 0.08); 0 1px 3px rgb(0 0 0 / 8%);
transition: all 0.3s cubic-bezier(0.2, 0, 0, 1); // MD3 emphasized easing transition: all 0.3s cubic-bezier(0.2, 0, 0, 1); // MD3 emphasized easing
svg { svg {
@@ -82,8 +83,8 @@ header {
&:hover { &:hover {
box-shadow: box-shadow:
0 2px 4px rgba(0, 0, 0, 0.14), // MD3 elevation-2 0 2px 4px rgb(0 0 0 / 14%), // MD3 elevation-2
0 3px 6px rgba(0, 0, 0, 0.10); 0 3px 6px rgb(0 0 0 / 10%);
transform: scale(1.02); // Subtle scale instead of translateY transform: scale(1.02); // Subtle scale instead of translateY
} }
} }
@@ -92,11 +93,9 @@ header {
font-size: 1.25rem; font-size: 1.25rem;
font-weight: 600; // MD3 label-large weight font-weight: 600; // MD3 label-large weight
letter-spacing: 0.01em; // MD3 tracking letter-spacing: 0.01em; // MD3 tracking
color: $foreground;
// Subtle gradient instead of animated // Subtle gradient instead of animated
background: linear-gradient(135deg, $foreground 0%, rgba($accent, 0.8) 100%); background: linear-gradient(135deg, $foreground 0%, rgb($accent / 80%) 100%);
-webkit-background-clip: text;
background-clip: text; background-clip: text;
color: transparent; color: transparent;
} }
@@ -127,11 +126,12 @@ header {
} }
// Header animations - MD3 style (subtle) // Header animations - MD3 style (subtle)
@keyframes fadeInDown { @keyframes fade-in-down {
from { from {
opacity: 0; opacity: 0;
transform: translateY(-4px); // Less dramatic transform: translateY(-4px); // Less dramatic
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
@@ -139,5 +139,5 @@ header {
} }
header { header {
animation: fadeInDown 0.3s cubic-bezier(0.2, 0, 0, 1); // MD3 easing animation: fade-in-down 0.3s cubic-bezier(0.2, 0, 0, 1); // MD3 easing
} }

View File

@@ -2,7 +2,7 @@
// Typography styles // Typography styles
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
font-family: var(--font-inter), 'Inter', sans-serif; font-family: var(--font-inter), Inter, sans-serif;
font-weight: 600; font-weight: 600;
line-height: 1.2; line-height: 1.2;
color: $foreground; color: $foreground;

View File

@@ -4,88 +4,241 @@
// Utility classes generator // Utility classes generator
@each $name, $value in vars.$spacing { @each $name, $value in vars.$spacing {
.p-#{$name} { padding: $value !important; } .p-#{$name} {
.px-#{$name} { padding-left: $value !important; padding-right: $value !important; } padding: $value !important;
.py-#{$name} { padding-top: $value !important; padding-bottom: $value !important; } }
.pt-#{$name} { padding-top: $value !important; }
.pr-#{$name} { padding-right: $value !important; } .px-#{$name} {
.pb-#{$name} { padding-bottom: $value !important; } padding-left: $value !important;
.pl-#{$name} { padding-left: $value !important; } padding-right: $value !important;
}
.m-#{$name} { margin: $value !important; }
.mx-#{$name} { margin-left: $value !important; margin-right: $value !important; } .py-#{$name} {
.my-#{$name} { margin-top: $value !important; margin-bottom: $value !important; } padding-top: $value !important;
.mt-#{$name} { margin-top: $value !important; } padding-bottom: $value !important;
.mr-#{$name} { margin-right: $value !important; } }
.mb-#{$name} { margin-bottom: $value !important; }
.ml-#{$name} { margin-left: $value !important; } .pt-#{$name} {
padding-top: $value !important;
.gap-#{$name} { gap: $value !important; } }
.pr-#{$name} {
padding-right: $value !important;
}
.pb-#{$name} {
padding-bottom: $value !important;
}
.pl-#{$name} {
padding-left: $value !important;
}
.m-#{$name} {
margin: $value !important;
}
.mx-#{$name} {
margin-left: $value !important;
margin-right: $value !important;
}
.my-#{$name} {
margin-top: $value !important;
margin-bottom: $value !important;
}
.mt-#{$name} {
margin-top: $value !important;
}
.mr-#{$name} {
margin-right: $value !important;
}
.mb-#{$name} {
margin-bottom: $value !important;
}
.ml-#{$name} {
margin-left: $value !important;
}
.gap-#{$name} {
gap: $value !important;
}
} }
// Flexbox utilities // Flexbox utilities
.flex { display: flex !important; } .flex {
.inline-flex { display: inline-flex !important; } display: flex !important;
.flex-row { flex-direction: row !important; } }
.flex-col { flex-direction: column !important; }
.flex-wrap { flex-wrap: wrap !important; } .inline-flex {
.flex-nowrap { flex-wrap: nowrap !important; } display: inline-flex !important;
.flex-1 { flex: 1 1 0% !important; } }
.flex-row {
flex-direction: row !important;
}
.flex-col {
flex-direction: column !important;
}
.flex-wrap {
flex-wrap: wrap !important;
}
.flex-nowrap {
flex-wrap: nowrap !important;
}
.flex-1 {
flex: 1 1 0% !important;
}
// Justify content // Justify content
.justify-start { justify-content: flex-start !important; } .justify-start {
.justify-end { justify-content: flex-end !important; } justify-content: flex-start !important;
.justify-center { justify-content: center !important; } }
.justify-between { justify-content: space-between !important; }
.justify-around { justify-content: space-around !important; } .justify-end {
justify-content: flex-end !important;
}
.justify-center {
justify-content: center !important;
}
.justify-between {
justify-content: space-between !important;
}
.justify-around {
justify-content: space-around !important;
}
// Align items // Align items
.items-start { align-items: flex-start !important; } .items-start {
.items-end { align-items: flex-end !important; } align-items: flex-start !important;
.items-center { align-items: center !important; } }
.items-stretch { align-items: stretch !important; }
.items-end {
align-items: flex-end !important;
}
.items-center {
align-items: center !important;
}
.items-stretch {
align-items: stretch !important;
}
// Grid // Grid
.grid { display: grid !important; } .grid {
.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)) !important; } display: grid !important;
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; } }
.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
.grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; } .grid-cols-1 {
grid-template-columns: repeat(1, minmax(0, 1fr)) !important;
}
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
}
.grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
}
.grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
}
// Border radius // Border radius
@each $name, $value in vars.$radius { @each $name, $value in vars.$radius {
.rounded-#{$name} { border-radius: $value !important; } .rounded-#{$name} {
border-radius: $value !important;
}
} }
// Text sizes // Text sizes
@each $name, $value in vars.$font-sizes { @each $name, $value in vars.$font-sizes {
.text-#{$name} { font-size: $value !important; } .text-#{$name} {
font-size: $value !important;
}
} }
// Font weights // Font weights
@each $name, $value in vars.$font-weights { @each $name, $value in vars.$font-weights {
.font-#{$name} { font-weight: $value !important; } .font-#{$name} {
font-weight: $value !important;
}
} }
// Text align // Text align
.text-left { text-align: left !important; } .text-left {
.text-center { text-align: center !important; } text-align: left !important;
.text-right { text-align: right !important; } }
.text-center {
text-align: center !important;
}
.text-right {
text-align: right !important;
}
// Colors // Colors
.text-foreground { color: vars.$foreground !important; } .text-foreground {
.text-muted-foreground { color: vars.$muted-foreground !important; } color: vars.$foreground !important;
.text-primary { color: vars.$primary !important; } }
.text-destructive { color: vars.$destructive !important; }
.text-accent { color: vars.$accent !important; }
.bg-background { background-color: vars.$background !important; } .text-muted-foreground {
.bg-card { background-color: vars.$card !important; } color: vars.$muted-foreground !important;
.bg-primary { background-color: vars.$primary !important; } }
.bg-secondary { background-color: vars.$secondary !important; }
.bg-muted { background-color: vars.$muted !important; } .text-primary {
.bg-accent { background-color: vars.$accent !important; } color: vars.$primary !important;
.bg-destructive { background-color: vars.$destructive !important; } }
.text-destructive {
color: vars.$destructive !important;
}
.text-accent {
color: vars.$accent !important;
}
.bg-background {
background-color: vars.$background !important;
}
.bg-card {
background-color: vars.$card !important;
}
.bg-primary {
background-color: vars.$primary !important;
}
.bg-secondary {
background-color: vars.$secondary !important;
}
.bg-muted {
background-color: vars.$muted !important;
}
.bg-accent {
background-color: vars.$accent !important;
}
.bg-destructive {
background-color: vars.$destructive !important;
}
// Border // Border
.border { border: 1px solid vars.$border !important; } .border { border: 1px solid vars.$border !important; }
@@ -138,6 +291,7 @@
// Space between children - DRY loop // Space between children - DRY loop
$space-values: (2, 3, 4, 6, 8); $space-values: (2, 3, 4, 6, 8);
@each $value in $space-values { @each $value in $space-values {
.space-y-#{$value} > * + * { margin-top: fn.spacing($value) !important; } .space-y-#{$value} > * + * { margin-top: fn.spacing($value) !important; }
.space-x-#{$value} > * + * { margin-left: fn.spacing($value) !important; } .space-x-#{$value} > * + * { margin-left: fn.spacing($value) !important; }
@@ -161,26 +315,26 @@ $space-values: (2, 3, 4, 6, 8);
padding-left: 1rem; padding-left: 1rem;
padding-right: 1rem; padding-right: 1rem;
@media (min-width: 640px) { @media (width >= 640px) {
max-width: 640px; max-width: 640px;
} }
@media (min-width: 768px) {
@media (width >= 768px) {
max-width: 768px; max-width: 768px;
} }
@media (min-width: 1024px) {
@media (width >= 1024px) {
max-width: 1024px; max-width: 1024px;
} }
@media (min-width: 1280px) {
@media (width >= 1280px) {
max-width: 1280px; max-width: 1280px;
} }
} }
// Additional positioning // Additional positioning
.inset-0 { .inset-0 {
top: 0 !important; inset: 0 !important;
right: 0 !important;
bottom: 0 !important;
left: 0 !important;
} }
.top-0 { top: 0 !important; } .top-0 { top: 0 !important; }
@@ -239,8 +393,7 @@ $space-values: (2, 3, 4, 6, 8);
} }
// Background clip // Background clip
.bg-clip-text { .bg-clip-text {
-webkit-background-clip: text !important;
background-clip: text !important; background-clip: text !important;
} }
@@ -252,7 +405,7 @@ $space-values: (2, 3, 4, 6, 8);
// Shadow variants // Shadow variants
.shadow-xs { .shadow-xs {
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05) !important; box-shadow: 0 1px 2px 0 rgb(0 0 0 / 5%) !important;
} }
// Underline offset // Underline offset
@@ -261,7 +414,9 @@ $space-values: (2, 3, 4, 6, 8);
} }
// Gap variations - only adding those NOT in spacing map // Gap variations - only adding those NOT in spacing map
.gap-1\.5 { gap: 0.375rem !important; } // 1.5 spacing not in map .gap-1-5 {
gap: 0.375rem !important;
} // 1.5 spacing not in map
// Rounded variations (additional) // Rounded variations (additional)
.rounded-xs { border-radius: 0.125rem !important; } .rounded-xs { border-radius: 0.125rem !important; }