lumina-sass 2.7.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,247 +1,140 @@
1
1
  # Lumina SASS
2
- *Last updated: 2026-06-05*
3
- Lumina Sass provides design tokens and mixins to help you build modern web applications.
4
2
 
5
- ## Overview
3
+ [![CI](https://github.com/NexusWeave/ux-lumina-sass/actions/workflows/ci.yml/badge.svg)](https://github.com/NexusWeave/ux-lumina-sass/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/lumina-sass.svg)](https://www.npmjs.com/package/lumina-sass)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
6
 
7
- Lumina SASS offers a collection of standardized color variables and utility mixins. The library uses clear naming conventions, making it simple to add to any SASS-based project.
7
+ **Lumina SASS** is a comprehensive design token and mixin framework engineered for modern web development. It provides a robust, standardized foundation for color systems, responsive layouts, and reusable components utilizing the **Sass Indented Syntax**.
8
8
 
9
- ## Installation
9
+ ---
10
+
11
+ ## Technical Specifications
12
+
13
+ Lumina SASS is architected with modularity and efficiency as core principles. Key features include:
14
+ - **Type Safety:** Leveraging Sass maps and sophisticated validation logic.
15
+ - **Architectural Consistency:** Standardized nomenclature for design tokens.
16
+ - **Enhanced Developer Experience:** An intuitive API featuring streamlined mixins.
17
+ - **Modern Standards Compliance:** Full compatibility with Dart Sass and the `@use` module system.
10
18
 
11
- Install the package as a project-level dependency in your project:
19
+ > **Note:** This library utilizes the **Sass Indented Syntax** (.sass). It remains compatible with SCSS projects via the `@use` directive. Demonstration examples employ the indented syntax to maintain consistency with the source codebase.
20
+
21
+ ## Installation
12
22
 
13
23
  ```bash
14
24
  npm install lumina-sass
15
25
  ```
16
26
 
17
- This will add `lumina-sass` to your `package.json` file. Do not install the library globally.
18
-
19
27
  ## Usage
20
28
 
21
- ### Importing the Library
22
-
23
- You can use the library directly in your Sass files using standard `@use` syntax.
29
+ Lumina SASS employs a modular architecture, permitting the importation of the entire framework or specific modules as required.
24
30
 
25
- #### 1. Import Flexbox Utilities (the only public export)
26
-
27
- You can import the flexbox utilities directly:
31
+ ### Importing Modules
28
32
 
29
33
  ```sass
30
- // In your style.sass or style.scss file:
31
- @use 'lumina-sass/flexbox' as flex;
32
-
33
- // Now all flexbox mixins and classes are available:
34
- .container {
35
- @include flex.flexbox-generator('flex');
36
- }
37
- ```
38
-
34
+ // Import flexbox utilities (recommended)
35
+ @use 'lumina-sass/flexbox' as flex
39
36
 
40
- #### 2. Import Specific Modules
37
+ // Import generator mixins
38
+ @use 'lumina-sass/generators' as gen
41
39
 
42
- > The package now exports the `flexbox` sub‑path and other public sub‑paths (`color`, `mix`). Other internal modules (`utils`, `map`, …) remain private.
43
-
44
-
45
- ### Module Breakdown
46
-
47
- | Module | Description |
48
- | :--- | :--- |
49
- | `lumina-sass/flexbox` | Flexbox utilities and CSS classes. |
50
- | `lumina-sass/color` | Color variables and palettes. |
51
- | `lumina-sass/mix` | General mixins (layout, typography, media). |
40
+ // Import descriptive color variables
41
+ @use 'lumina-sass/colors' as color
52
42
 
43
+ // Import general mixins (typography, layout, accessibility)
44
+ @use 'lumina-sass/mixins' as mix
53
45
 
54
- ### Utility Classes
46
+ // Import design tokens and maps
47
+ @use 'lumina-sass/map' as map
55
48
 
56
- If you prefer to use CSS classes directly in your HTML (like `.flex-center`), please check our [**Utility Classes Guide**](docs/utils/utility_classes.md).
49
+ // Import general utility functions
50
+ @use 'lumina-sass/func' as func
51
+ ```
57
52
 
58
- ### Semantic Media Queries
59
- For common media queries, you can use these simple helper mixins to make your code more readable.
53
+ ### Implementation Examples
60
54
 
55
+ #### Flexbox Layout
61
56
  ```sass
62
- .my-component
63
- // Base styles
64
- background: white
65
-
66
- // Applies styles for medium screens and smaller
67
- @include on-breakpoint(md)
68
- font-size: 0.9rem
69
-
70
- // Applies styles when the user prefers dark mode
71
- @include on-dark-mode
72
- background: black
57
+ .container
58
+ @include flex.flexbox-generator('flex-row')
59
+ @include flex.flex-items-center
73
60
  ```
74
61
 
75
- Available helpers:
76
- - `@include on-breakpoint($name)`
77
- - `@include on-dark-mode`
78
- - `@include on-light-mode`
79
- - `@include on-landscape`
80
- - `@include on-portrait`
81
-
82
- ## Features
83
- ### Recent Changes
84
-
85
- - **RGB conversion:** All colour variables that previously used `rgba(..., 1)` are now simplified to `rgb(...)`; any hexadecimal literals have been converted to `rgb()`.
86
- ### Standardized Colors
87
- Uses a consistent `$[brand]-[color]` pattern for easy use and maintenance.
88
- - **Brand Colors:** Social media platforms, operating systems, and tech brands.
89
- - **UI States:** Hover and active states.
90
-
91
- ### Flexbox Utilities
92
- A complete set of flexbox mixins and maps to help you build layouts quickly.
93
-
94
- ### Utility Mixins
95
- - **Responsive Design:** Media query breakpoints.
96
- - **Responsive Media Queries:** Added `media-queries` mixin usage in demo and `device-media` support for iPhone.
97
- - **Typography:** Font handling and text styling.
98
- - **Elements:** Button generation and image styling.
99
-
100
- ---
101
-
102
- ## Contributing & Internal Docs
103
-
104
- To learn how to contribute or understand the release process, please see:
105
-
106
- - [**Development Guide**](docs/developer/development.md) - Project structure and setup rules.
107
- - [**Testing Guide**](docs/developer/testing.md) - How to write and run Sass unit tests.
108
- - [**Releasing & Publishing**](docs/developer/releasing.md) - Details on the release process.
109
-
110
- ---
111
-
112
- # AI Operations Guide for **lumina-sass**
113
-
114
- > This document is intended for the Antigravity AI (or any other automated assistant) that contributes to the `lumina-sass` project. It consolidates the repository‑specific conventions, tooling, and policies that enable the AI to work safely, efficiently, and in compliance with the user’s personal rules.
115
-
116
- ---
117
-
118
- ## 1️⃣ Project Overview
119
- - **Name:** `lumina-sass`
120
- - **Purpose:** Provides design tokens, mixins, and flexbox utilities for Sass‑based web projects.
121
- - **Primary public entry point:** `lumina-sass/flexbox` (the only sub‑path exported in `package.json`).
122
- - **Main files:**
123
- - `src/_index.sass` – default entry (re‑exports flexbox).
124
- - `src/flexbox/_index.sass` – collection of flexbox mixins and utility classes.
125
- - `README.md` – user‑facing documentation (kept up‑to‑date with export changes).
126
-
127
- ---
128
-
129
- ## 2️⃣ Development Environment (User‑defined rules)
130
- - **Node.js version:** Use the latest **Stable LTS** (v24.x) via `fnm`.
131
- ```bash
132
- fnm use lts # activates the stable LTS version
133
- ```
134
- - **Package manager:** `npm` (default for this repo).
135
- - **GPG signing:** All commits must be **GPG‑signed** (`git commit -S`). The AI should stage changes and let the user provide the pass‑phrase; never use `--no-gpg-sign`.
136
- - **Conventional Commits:** Follow the `type: description.` format, ending with a period. Emphasise *why* a change is made.
137
- - **Python tools:** When needed, create a virtual environment with `python -m venv .venv` (not required for this repo, but noted for future scripts).
138
-
139
- ---
62
+ #### Automated Generation (Icons & Inputs)
63
+ ```sass
64
+ // Systematically generate all icon classes
65
+ @include gen.icon-generator()
140
66
 
141
- ## 3️⃣ Repository Layout (important paths)
67
+ // Apply base styling to all text inputs
68
+ @include gen.input-generator('text')
142
69
  ```
143
- lumina-sass/
144
- ├─ src/ # Sass source files
145
- │ ├─ _index.sass # Default entry point (re‑exports flexbox)
146
- │ ├─ flexbox/ # Public module – only exported sub‑path
147
- │ │ ├─ _index.sass
148
- │ │ └─ …
149
- │ └─ (other internal directories: color/, mix/, utils/, map/)
150
- ├─ dist/ # Build artefacts (generated by `npm run build`)
151
- ├─ docs/ # Additional documentation
152
- │ └─ ai_guide.md # **This file** – AI reference guide
153
- ├─ README.md # Consumer‑facing docs – kept in sync with exports
154
- ├─ package.json
155
- └─ ...
156
- ```
157
-
158
- ---
159
-
160
- ## 4️⃣ Core Tasks for the AI
161
- | Task | How the AI should perform it | Important notes |
162
- |------|-----------------------------|----------------|
163
- | **Edit files** | Use `replace_file_content` for a single contiguous block or `multi_replace_file_content` for multiple non‑adjacent edits. Never overwrite a whole file with `write_to_file` unless explicitly creating a new artifact. | Preserve existing comments and docstrings. |
164
- | **Stage changes** | `git add <file>` after editing. |
165
- | **Commit** | `git commit -S -m "<Conventional Commit>"`. The AI must describe the command before execution and ensure GPG signing is enabled. |
166
- | **Run builds** | `npm run build` (or `npm run dev` if a dev server is needed). Ensure the LTS Node version is active via `fnm`. |
167
- | **Verify exports** | Test that `import 'lumina-sass/flexbox'` works and that importing any other sub‑path fails with `Package subpath ... is not defined`. |
168
- | **Update documentation** | Keep `README.md` and any internal docs in sync with code changes, especially the `exports` field. |
169
- | **Memory synchronization** | Whenever the AI updates a file that is part of the user’s memory (e.g., global or project‑specific memory files), also copy the changes to `/home/kristoffer/Gdrive/Administration/Gemini-Memory-Backup/`. |
170
-
171
- ---
172
70
 
173
- ## 5️⃣ Export Management (Key AI Responsibility)
174
- - The `package.json` **exports** block defines the public API. The AI must:
175
- 1. Ensure only the intended sub‑paths are listed (currently `.` and `./flexbox`).
176
- 2. Update the **module breakdown table** in `README.md` to reflect the exported modules.
177
- 3. When new public modules are added, remember to:
178
- - Add them to `exports`.
179
- - Update the README table.
180
- - Adjust the documentation guide.
181
- - Any attempt to expose internal modules (`color`, `mixins`, `utils`, `map`) must be rejected unless the user explicitly asks for it.
71
+ #### Accessibility (WCAG Contrast Verification)
72
+ ```sass
73
+ .alert
74
+ background: color.$brand-lumina-blue
75
+ color: color.$neutral-white
76
+ // Triggers a build failure if the contrast ratio falls below 4.5:1
77
+ @include mix.assert-contrast(color.$neutral-white, color.$brand-lumina-blue)
78
+ ```
79
+ > For comprehensive details, please refer to our [**Color Contrast & Accessibility Guide**](docs/colors/contrast.md).
182
80
 
183
- ---
81
+ #### Pure Functions (Mathematical & Logical Utilities)
82
+ ```sass
83
+ .custom-bg
84
+ // Determine the relative luminance of a brand color
85
+ $luminance: func.luminance(color.$brand-lumina-blue)
86
+ opacity: if($luminance > 0.5, 0.8, 1)
87
+ ```
184
88
 
185
- ## 6️⃣ Testing & Verification Workflow
186
- 1. **Run Unit Tests**
187
- ```bash
188
- npm test
189
- ```
190
- 2. **Local import test**
191
- ```bash
192
- node -e "import 'lumina-sass/flexbox'" # should succeed
193
- node -e "import 'lumina-sass/utils'" # should fail
194
- ```
195
- 2. **Build**
196
- ```bash
197
- npm run build
198
- ```
199
- 3. **Run demo** (optional) to ensure compiled CSS works:
200
- ```bash
201
- npm run serve # serves the demo folder via http‑server
202
- ```
203
- 4. **Commit verification**: After committing, run `git log --show-signature -1` to confirm the GPG signature is present.
89
+ #### Semantic Breakpoints
90
+ ```sass
91
+ .card
92
+ width: 100%
93
+ @include mix.on-breakpoint(md)
94
+ width: 50%
95
+ ```
204
96
 
205
- ---
97
+ ## Public API Reference (Sub-paths)
206
98
 
207
- ## 7️⃣ Contribution Guidelines (for AI and humans)
208
- - **Pull‑request workflow:**
209
- 1. Create a feature branch.
210
- 2. Make the required edits.
211
- 3. Run the verification steps above.
212
- 4. Commit with a signed Conventional Commit.
213
- 5. Push and open a PR.
214
- - **Documentation:** Every public change must be reflected in `README.md` and, if relevant, in the AI guide.
215
- - **Linting / Formatting:** Keep the repo formatted according to the existing style (Sass indentation, no trailing spaces).
99
+ | Path | Description |
100
+ | :--- | :--- |
101
+ | `lumina-sass` | Primary entry point (includes common utilities). |
102
+ | `lumina-sass/flexbox` | Comprehensive flexbox mixins and utility classes. |
103
+ | `lumina-sass/color` | Standardized brand and UI color palettes. |
104
+ | `lumina-sass/mix` | Primary mixins for typography, media queries, and structural elements. |
105
+ | `lumina-sass/map` | Internal configurations and design tokens. |
106
+ | `lumina-sass/contrast` | Automated WCAG contrast ratio verification. |
107
+ | `lumina-sass/func` | Specialized Sass functions for mathematics, logic, and searching. |
216
108
 
217
- ---
109
+ ## Key Features
218
110
 
219
- ## 8️⃣ Quick Reference Commands (AI‑friendly)
220
- | Purpose | Command |
221
- |---------|---------|
222
- | Activate LTS Node | `fnm use lts` |
223
- | Install dependencies | `npm install` |
224
- | Build the package | `npm run build` |
225
- | Run tests | `npm test` |
226
- | Serve demo (optional) | `npm run serve` |
227
- | Stage a file | `git add <path>` |
228
- | Signed commit (example) | `git commit -S -m "feat: description of change."` |
229
- | Verify signature | `git log --show-signature -1` |
230
- | Test valid import | `node -e "import 'lumina-sass/flexbox'"` |
231
- | Test invalid import | `node -e "import 'lumina-sass/utils'"` |
111
+ - **Standardized Palettes:** Consistent `$brand-color` patterns utilizing `rgb()` for maximum compatibility.
112
+ - **Automated Accessibility:** Integrated WCAG contrast ratio verification.
113
+ - **Specialized Functions:** Dedicated modules for mathematical operations and font stack resolution.
114
+ - **Responsive Utilities:** Intuitive media query helpers (e.g., `on-breakpoint`, `on-dark-mode`).
115
+ - **Flexbox Engine:** A robust suite of mixins for rows, columns, and sophisticated alignment.
232
116
 
233
- ---
117
+ ## Developer Resources
234
118
 
235
- ## 9️⃣ Contact & Further Help
236
- - For any ambiguity, the AI should ask the user via a clarifying question before proceeding.
237
- - The AI must always **present a plan before executing** any non‑trivial change (as per user‑global rules).
119
+ - [**Documentation Index**](docs/README.md)
120
+ - [**Development Guide**](docs/developer/development.md) Technical overview and contribution workflows.
121
+ - [**Testing Suite**](docs/developer/testing.md) Detailed specifications for unit testing and code analysis.
122
+ - [**Sass Testing Quick-Start**](docs/developer/testing.md#unit-testing-with-sass-true) – Direct access to testing methodologies.
123
+ - [**Utility Classes**](docs/utils/utility_classes.md) – A comprehensive inventory of pre-configured CSS classes.
124
+ - [**AI Operations Guide**](docs/ai_guide.md) – Guidance for automated assistant integration.
238
125
 
239
- ---
126
+ ## Contributing
240
127
 
241
- *This guide is version‑controlled along with the rest of the repository, ensuring the AI always has an up‑to‑date reference when working on `lumina-sass`.*
128
+ We welcome contributions to the project. Please consult our [Development Guide](docs/developer/development.md) and ensure that all tests pass successfully prior to submitting a pull request.
242
129
 
130
+ ```bash
131
+ # Execute unit testing suite
132
+ npm test
243
133
 
134
+ # Execute stylistic analysis
135
+ npm run lint:sass
136
+ ```
244
137
 
245
138
  ## License
246
139
 
247
- MIT
140
+ This project is licensed under the terms of the [MIT License](LICENSE).
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "lumina-sass",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
+ "type": "module",
4
5
  "description": "Lumina Sass design tokens, mixins and public sub-modules (flexbox, color, mix).",
5
6
  "main": "src/_index.sass",
6
7
  "sass": "src/_index.sass",
@@ -13,10 +14,22 @@
13
14
  "sass": "./src/flexbox/_index.sass",
14
15
  "default": "./src/flexbox/_index.sass"
15
16
  },
17
+ "./generators": {
18
+ "sass": "./src/mix/_generators.sass",
19
+ "default": "./src/mix/_generators.sass"
20
+ },
21
+ "./mixins": {
22
+ "sass": "./src/mix/_index.sass",
23
+ "default": "./src/mix/_index.sass"
24
+ },
16
25
  "./color": {
17
26
  "sass": "./src/color/_index.sass",
18
27
  "default": "./src/color/_index.sass"
19
28
  },
29
+ "./colors": {
30
+ "sass": "./src/color/_index.sass",
31
+ "default": "./src/color/_index.sass"
32
+ },
20
33
  "./mix": {
21
34
  "sass": "./src/mix/_index.sass",
22
35
  "default": "./src/mix/_index.sass"
@@ -24,6 +37,14 @@
24
37
  "./map": {
25
38
  "sass": "./src/map/_index.sass",
26
39
  "default": "./src/map/_index.sass"
40
+ },
41
+ "./contrast": {
42
+ "sass": "./src/mix/_contrast.sass",
43
+ "default": "./src/mix/_contrast.sass"
44
+ },
45
+ "./func": {
46
+ "sass": "./src/func/_index.sass",
47
+ "default": "./src/func/_index.sass"
27
48
  }
28
49
  },
29
50
  "repository": {
@@ -33,11 +54,12 @@
33
54
  "scripts": {
34
55
  "serve": "http-server demo",
35
56
  "release": "standard-version",
57
+ "lint:sass": "tsx test/ts/syntax-check.ts",
36
58
  "dev": "npm run build && npm run serve",
37
- "build:demo": "sass demo/style.sass demo/style.css",
38
- "build": "sass src/_index.sass test/index.css && sass src/color/_index.sass test/color.css && sass src/mix/_index.sass test/mix.css && sass src/flexbox/_index.sass test/flexbox.css && sass src/map/_index.sass test/map.css",
39
- "test:sass": "sass src/test/index.spec.sass src/test/index.spec.css",
40
- "test": "npm run test:sass"
59
+ "module-test": "tsx test/ts/module-test.ts",
60
+ "build": "sass demo/style.sass demo/style.css",
61
+ "test:sass": "sass test/index.spec.sass test/index.spec.css",
62
+ "test": "npm run test:sass && npm run lint:sass && npm run module-test"
41
63
  },
42
64
  "files": [
43
65
  "src"
@@ -45,9 +67,15 @@
45
67
  "author": "",
46
68
  "license": "MIT",
47
69
  "devDependencies": {
70
+ "@types/node": "^25.9.2",
48
71
  "http-server": "^14.1.1",
72
+ "postcss-sass": "^0.5.0",
49
73
  "sass": "^1.85.1",
50
74
  "sass-true": "^10.1.0",
51
- "standard-version": "^9.5.0"
75
+ "standard-version": "^9.5.0",
76
+ "stylelint": "^17.13.0",
77
+ "stylelint-config-standard-scss": "^17.0.0",
78
+ "tsx": "^4.22.4",
79
+ "typescript": "^6.0.3"
52
80
  }
53
81
  }
package/src/_index.sass CHANGED
@@ -1,7 +1,9 @@
1
1
  @forward 'mix'
2
+ @forward 'func'
2
3
  @forward 'color'
3
4
  @forward 'flexbox'
4
5
 
6
+
5
7
  *, *::before, *::after
6
8
  box-sizing: border-box
7
9
  writing-mode: horizontal-tb
@@ -1,3 +1,3 @@
1
1
  $accent-salmon: rgb(255, 119, 119)
2
- $accent-slate-blue: rgb(123, 104, 238)
3
- $accent-lavender: rgb(230, 230, 250)
2
+ $accent-lavender: rgb(230, 230, 250)
3
+ $accent-slate-blue: rgb(123, 104, 238)
@@ -1,5 +1,6 @@
1
1
  @use '../mix/index' as mix
2
2
 
3
+ @forward '../mix/index'
3
4
  @forward 'flexbox-row'
4
5
  @forward 'flexbox-column'
5
6
  @forward 'flexbox-wrap-row'
@@ -0,0 +1,26 @@
1
+ @use 'sass:math'
2
+ @use 'sass:color'
3
+
4
+ /// Calculates the relative luminance of a color
5
+ /// @param {Color} $color - The color to calculate luminance for
6
+ /// @return {Number} - The relative luminance (0 to 1)
7
+ @function luminance($color)
8
+ $red: math.div(color.channel($color, "red", $space: rgb), 255)
9
+ $green: math.div(color.channel($color, "green", $space: rgb), 255)
10
+ $blue: math.div(color.channel($color, "blue", $space: rgb), 255)
11
+
12
+ $r: if($red <= 0.03928, math.div($red, 12.92), math.pow(math.div($red + 0.055, 1.055), 2.4))
13
+ $g: if($green <= 0.03928, math.div($green, 12.92), math.pow(math.div($green + 0.055, 1.055), 2.4))
14
+ $b: if($blue <= 0.03928, math.div($blue, 12.92), math.pow(math.div($blue + 0.055, 1.055), 2.4))
15
+
16
+ @return $r * 0.2126 + $g * 0.7152 + $b * 0.0722
17
+
18
+ /// Calculates the contrast ratio between two colors
19
+ /// @param {Color} $color1 - The first color
20
+ /// @param {Color} $color2 - The second color
21
+ /// @return {Number} - The contrast ratio (1 to 21)
22
+ @function contrast-ratio($color1, $color2)
23
+ $l1: luminance($color1)
24
+ $l2: luminance($color2)
25
+
26
+ @return math.div(math.max($l1, $l2) + 0.05, math.min($l1, $l2) + 0.05)
@@ -0,0 +1,8 @@
1
+ @use 'sass:map' as map
2
+ @use '../map/icons' as icon-map
3
+
4
+ @function find($name)
5
+ @each $category, $maps in icon-map.$icons
6
+ @if map.has-key($maps, $name)
7
+ @return map.get($maps, $name)
8
+ @return null
@@ -0,0 +1,3 @@
1
+ @forward 'color'
2
+ @forward 'typography'
3
+ @forward 'icons'
@@ -0,0 +1,40 @@
1
+ @use 'sass:map'
2
+ @use 'sass:list'
3
+ @use '../map/fonts' as fonts
4
+
5
+ @function get-default-stack($category)
6
+ @if not map.has-key(fonts.$fonts, $category)
7
+ @return null
8
+ $map: map.get(fonts.$fonts, $category)
9
+ $keys: map.keys($map)
10
+ $generic: $category
11
+ @if $category == 'mono'
12
+ $generic: monospace
13
+ @return list.append($keys, $generic)
14
+
15
+ @function is-known-font($font)
16
+ @if $font == null
17
+ @return false
18
+ @if map.has-key(fonts.$fonts, $font)
19
+ @return true
20
+ @each $category, $map in fonts.$fonts
21
+ @if map.has-key($map, $font)
22
+ @return true
23
+ @return false
24
+
25
+ // Helper: return the generic family for a given font name using the fonts map.
26
+ @function font-family-of($font)
27
+ @if $font == null
28
+ @return ('Nunito', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif)
29
+
30
+ @if map.has-key(fonts.$fonts, $font)
31
+ @if $font == 'mono'
32
+ @return monospace
33
+ @return $font
34
+
35
+ @each $category, $map in fonts.$fonts
36
+ @if map.has-key($map, $font)
37
+ @return map.get($map, $font)
38
+
39
+ // Default fallback stack when font is not found
40
+ @return ('Nunito', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif)
@@ -10,7 +10,6 @@ $flex-wrap-reversed-row: ('display': flex, 'flex-wrap': wrap, 'flex-direction':
10
10
  $flex-wrap-reversed-col: ('display': flex, 'flex-wrap': wrap, 'flex-direction': column-reverse)
11
11
 
12
12
 
13
-
14
13
  $flexbox:(
15
14
  'flex': $flex,
16
15
  'flex-row': $flex-row,
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
  $academic: ('school': (icon: "\F671"), 'diploma': (icon: "\F11D"))
5
- $utility-inputs: ('color': (icon: '\F4B0'), 'hidden': (icon: '\F0E7'))
5
+ $icon-utility-mappings: ('color': (icon: '\F4B0'), 'hidden': (icon: '\F0E7'))
6
6
  $boolean-controls: ('radio': (icon: '\F110'), 'checkbox': (icon: '\F272'))
7
7
  $video-controls: ('play-video': (icon: '\F4F4'), 'pause-video': (icon: '\F4C4'))
8
8
  $documents: ('pdf': (icon: "\F63D"), 'dir': (icon: "\F3D7"), 'default': (icon: "\F369"))
@@ -14,7 +14,7 @@ $communication: ('email': (icon: "\F84B"), 'mail': (icon: "\F32F"), 'github': (i
14
14
 
15
15
  $icons: (
16
16
  'academic': $academic, 'document': $documents, 'misc-icons': $misc-icons,
17
- 'communication': $communication, 'utility-inputs': $utility-inputs,
17
+ 'communication': $communication, 'utility-inputs': $icon-utility-mappings,
18
18
  'input-controls': $input-controls, 'video-controls': $video-controls,
19
19
  'boolean-controls': $boolean-controls, 'datetime-pickers': $datetime-pickers,
20
20
  )
@@ -1,5 +1,6 @@
1
+ @forward 'fonts'
2
+ @forward 'inputs'
1
3
  @forward 'icons'
2
4
  @forward 'flexbox'
3
5
  @forward 'tag-theme'
4
-
5
6
  @forward 'devices-breakpoints'
@@ -1,5 +1,5 @@
1
1
  $booleanControls: ( 'radio', 'checkbox' )
2
- $utility-inputs: ( 'range', 'color', 'hidden' )
2
+ $input-utility-types: ( 'range', 'color', 'hidden' )
3
3
  $buttons: ( 'file', 'submit', 'reset', 'button')
4
4
  $datetimePickers: ( 'date', 'time', 'week', 'month', 'datetime-local' )
5
5
  $inputControls:( 'tel', 'url', 'text', 'email', 'search','number','password' )
@@ -7,7 +7,7 @@ $inputControls:( 'tel', 'url', 'text', 'email', 'search','number','password' )
7
7
  $inputs: (
8
8
  'buttons': $buttons,
9
9
  'inputControls': $inputControls,
10
- 'utility-inputs': $utility-inputs,
10
+ 'utility-inputs': $input-utility-types,
11
11
  'booleanControls': $booleanControls,
12
12
  'datetimePickers': $datetimePickers,
13
13
 
@@ -0,0 +1,11 @@
1
+ @use '../func/color' as func-color
2
+
3
+ /// Throws an architectural error if the contrast ratio between two colors fails to meet the specified threshold.
4
+ /// This mixin ensures that color combinations adhere to WCAG accessibility standards during the compilation process.
5
+ /// @param {Color} $foreground - The foreground color to be evaluated.
6
+ /// @param {Color} $background - The background color against which contrast is measured.
7
+ /// @param {Number} $threshold [4.5] - The minimum acceptable contrast ratio (standard WCAG AA compliance is 4.5:1).
8
+ @mixin assert-contrast($foreground, $background, $threshold: 4.5)
9
+ $ratio: func-color.contrast-ratio($foreground, $background)
10
+ @if $ratio < $threshold
11
+ @error "Accessibility Failure: The contrast ratio of #{$ratio} between #{$foreground} and #{$background} does not meet the required threshold of #{$threshold}:1."
@@ -31,4 +31,4 @@
31
31
 
32
32
  color: $color
33
33
  cursor: pointer
34
- @include typo.text-adjustments()
34
+ @include typo.text-adjustments($quiet: true)
@@ -6,15 +6,10 @@
6
6
  @use '../map/icons' as icon-map
7
7
  @use '../map/tag-theme' as tag-map
8
8
  @use '../map/flexbox' as flexbox-mapping
9
-
10
- @function _icon-find($name)
11
- @each $category, $maps in icon-map.$icons
12
- @if map.has-key($maps, $name)
13
- @return map.get($maps, $name)
14
- @return null
9
+ @use '../func/icons' as func-icons
15
10
 
16
11
  @mixin _icon-base($name, $color, $font-family)
17
- $props: _icon-find($name)
12
+ $props: func-icons.find($name)
18
13
  @if $props
19
14
  .#{$name}
20
15
  &::before
@@ -3,4 +3,5 @@
3
3
  @forward 'generators'
4
4
  @forward 'buttons'
5
5
  @forward 'elements'
6
- @forward 'misc-styling'
6
+ @forward 'misc-styling'
7
+ @forward 'contrast'
@@ -1,9 +1,9 @@
1
-
2
1
  @use 'sass:map'
3
2
  @use 'sass:list'
4
3
  @use 'sass:meta'
5
4
  @use 'sass:string'
6
5
  @use '../map/fonts' as fonts
6
+ @use '../func/typography' as func-typo
7
7
 
8
8
  @mixin text-wrap-safe($inline: 0)
9
9
  p, h1, h2, h3, h4, h5, h6, figcaption, a, li
@@ -13,15 +13,15 @@
13
13
  overflow-wrap: anywhere
14
14
  min-inline-size: $inline
15
15
 
16
- @mixin font( $font:null, $size: 1rem, $family: null, $style: null, $weight: null, $line-height: null, $variant: null)
17
- $detected-family: font-family-of($font)
16
+ @mixin font( $font:null, $size: 1rem, $family: null, $style: null, $weight: null, $line-height: null, $variant: null, $quiet: false)
17
+ $detected-family: func-typo.font-family-of($font)
18
18
 
19
- @if is-known-font($font)
19
+ @if func-typo.is-known-font($font)
20
20
  $family: $detected-family
21
21
 
22
22
  @else if $family == null
23
23
  $family: $detected-family
24
- @if $font != null
24
+ @if $font != null and $quiet == false
25
25
  @warn "Font '#{$font}' not found in configuration map. Defaulting to stack: '#{$font}', #{$family}."
26
26
 
27
27
  @if meta.type-of($font) == 'list'
@@ -49,59 +49,28 @@
49
49
  @if $variant != null
50
50
  font-variant: $variant
51
51
 
52
- @function get-default-stack($category)
53
- @if not map.has-key(fonts.$fonts, $category)
54
- @return null
55
- $map: map.get(fonts.$fonts, $category)
56
- $keys: map.keys($map)
57
- $generic: $category
58
- @if $category == 'mono'
59
- $generic: monospace
60
- @return list.append($keys, $generic)
61
-
62
52
  @mixin sans-serif($font: null, $size: 1rem, $weight: null, $style: null)
63
53
  @if $font == null
64
- $font: get-default-stack('sans-serif')
54
+ $font: func-typo.get-default-stack('sans-serif')
65
55
  @include font($font, $size, sans-serif, $style, $weight)
66
56
 
67
57
  @mixin serif($font: null, $size: 1rem, $weight: null, $style: null)
68
58
  @if $font == null
69
- $font: get-default-stack('serif')
59
+ $font: func-typo.get-default-stack('serif')
70
60
  @include font($font, $size, serif, $style, $weight)
71
61
 
72
62
  @mixin monospace($font: null, $size: 1rem, $weight: null, $style: null)
73
63
  @if $font == null
74
- $font: get-default-stack('mono')
64
+ $font: func-typo.get-default-stack('mono')
75
65
  @include font($font, $size, monospace, $style, $weight)
76
66
 
77
- @function is-known-font($font)
78
- @if $font == null
79
- @return false
80
- @if map.has-key(fonts.$fonts, $font)
81
- @return true
82
- @each $category, $map in fonts.$fonts
83
- @if map.has-key($map, $font)
84
- @return true
85
- @return false
86
-
87
- // Helper: return the generic family for a given font name using the fonts map.
88
- @function font-family-of($font)
89
- @if $font == null
90
- @return ('Nunito', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif)
91
-
92
- @if map.has-key(fonts.$fonts, $font)
93
- @if $font == 'mono'
94
- @return monospace
95
- @return $font
96
-
97
- @each $category, $map in fonts.$fonts
98
- @if map.has-key($map, $font)
99
- @return map.get($map, $font)
100
-
101
- // Default fallback stack when font is not found
102
- @return ('Nunito', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif)
67
+ @mixin line-clamp($lines: 3)
68
+ display: -webkit-box
69
+ -webkit-line-clamp: $lines
70
+ -webkit-box-orient: vertical
71
+ overflow: hidden
103
72
 
104
- @mixin text-adjustments($alignment: null, $decoration: null)
73
+ @mixin text-adjustments($alignment: null, $decoration: null, $quiet: false)
105
74
  @if $alignment != null
106
75
  text-align: $alignment
107
76
 
@@ -110,4 +79,5 @@
110
79
 
111
80
  @if $alignment == null and $decoration == null
112
81
  text-decoration: none
113
- @warn "No parameters provided for text-adjustments mixin. Default value present."
82
+ @if $quiet == false
83
+ @warn "No parameters provided for text-adjustments mixin. Default value present."
@@ -1,40 +0,0 @@
1
- @use 'sass:meta'
2
- @use '../_buttons' as buttons
3
- @use '../../../node_modules/sass-true' as true
4
-
5
- @include true.test-module('Buttons')
6
- @include true.test('Applies base button styling')
7
- @include true.assert
8
- @include true.output
9
- button
10
- @include buttons.base-btn()
11
-
12
- @include true.expect
13
- button
14
-
15
- border: none
16
- margin: 0.5em
17
- font-size: 1em
18
- cursor: pointer
19
- font-weight: bold
20
- font-style: normal
21
- position: relative
22
- padding: 0.5em 1.5em
23
- border-radius: 0.5em
24
- display: inline-block
25
- color: rgb(255, 248, 241)
26
- background-color: rgb(252, 245, 235)
27
- transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), background-color 0.2s
28
-
29
- &:hover
30
- transform: scale(1.05)
31
- background-color: rgb(248.6739130435, 233.9130434783, 212.8260869565)
32
-
33
- &:active
34
- transform: scale(0.95)
35
- background-color: rgb(245.347826087, 222.8260869565, 190.652173913)
36
-
37
- &:disabled
38
- opacity: 0.3
39
- cursor: not-allowed
40
-
@@ -1,38 +0,0 @@
1
- @use 'sass:meta'
2
- @use '../_elements' as elements
3
- @use '../../../node_modules/sass-true' as true
4
-
5
- @include true.test-module('Elements')
6
- @include true.test('Applies link colors and properties')
7
- @include true.assert
8
- @include true.output
9
- @include elements.link-color(rgb(0, 0, 255), rgb(0, 0, 200), rgb(0, 0, 150), rgb(128, 0, 128))
10
-
11
- @include true.expect
12
- a
13
- color: rgb(0, 0, 255)
14
- cursor: pointer
15
- text-decoration: none
16
-
17
- [aria-disabled="true"]
18
- color: rgb(160, 160, 160)
19
- cursor: not-allowed
20
- pointer-events: none
21
- text-decoration: none
22
-
23
- &:active
24
- color: rgb(0, 0, 150)
25
-
26
- &.external-link
27
- text-decoration: underline
28
-
29
- @media (hover: hover)
30
- &:hover
31
- color: rgb(0, 0, 200)
32
- border-radius: 0.5em
33
-
34
- &:visited
35
- color: rgb(128, 0, 128)
36
-
37
- h1, h2, h3, h4, h5, h6
38
- color: rgb(0, 0, 255) !important
@@ -1,63 +0,0 @@
1
- @use 'sass:meta'
2
- @use '../_generators' as generators
3
- @use '../../../node_modules/sass-true' as true
4
-
5
- @include true.test-module('Icon Generator')
6
- @include true.test('Generates school icon class')
7
- @include true.assert
8
- @include true.output
9
- @include generators.icon-generator('school')
10
-
11
- @include true.expect
12
- .school
13
- &::before
14
- color: rgb(64, 64, 64) !important
15
- font-family: 'bootstrap-icons'
16
- content: "\F671"
17
-
18
- @include true.test-module('Flexbox Generator')
19
- @include true.test('Generates flex-row properties')
20
- @include true.assert
21
- @include true.output
22
- @include generators.flexbox-generator('flex-row')
23
-
24
- @include true.expect
25
- display: flex
26
- flex-wrap: nowrap
27
- flex-direction: row
28
-
29
- @include true.test-module('Input Generator')
30
- @include true.test('Generates text input type')
31
- @include true.assert
32
- @include true.output
33
- @include generators.input-generator('text')
34
-
35
- @include true.expect
36
- input[type="text"]
37
- cursor: text
38
- font-size: 1rem
39
- line-height: 1.5
40
- padding: 0.5rem 1rem
41
- border-radius: 0.5rem
42
- box-sizing: border-box
43
- focus-outline: rgb(0, 120, 215)
44
- background-color: rgb(255, 255, 255)
45
- border: rgb(204, 204, 204) solid 0.0625rem
46
- outline: 0.0625rem solid rgb(0, 120, 215)
47
-
48
- input[type="text"]::focus
49
- outline: rgb(0, 120, 215)
50
-
51
- &::-webkit-slider-runnable-track
52
- block-size: 0.4rem
53
- background: #ddd
54
- border-radius: 0.2rem
55
-
56
- &::-webkit-slider-thumb
57
- -webkit-appearance: none
58
- inline-size: 1rem
59
- block-size: 1rem
60
- background: #0078d7
61
- border-radius: 50%
62
- margin-top: -0.3rem
63
-
@@ -1,35 +0,0 @@
1
- @use 'sass:meta'
2
- @use '../_media' as media
3
- @use '../../../node_modules/sass-true' as true
4
-
5
- @include true.test-module('Media Queries')
6
- @include true.test('Generates max-width media query for breakpoint md')
7
- @include true.assert
8
- @include true.output
9
- @include media.media-queries('md')
10
- color: blue
11
-
12
- @include true.expect
13
- @media (max-inline-size: 64rem)
14
- color: blue
15
-
16
- @include true.test('Generates prefers-color-scheme')
17
- @include true.assert
18
- @include true.output
19
- @include media.prefers-color-scheme(dark)
20
- background: black
21
-
22
- @include true.expect
23
- @media (prefers-color-scheme: dark)
24
- background: black
25
-
26
- @include true.test('Generates device-media for iphone')
27
- @include true.assert
28
- @include true.output
29
- @include media.device-media('iphone')
30
- color: white
31
-
32
- @include true.expect
33
- @media only screen and (min-inline-size: 20rem) and (max-inline-size: 20.125rem) and (min-block-size: 30rem) and (max-block-size: 30.125rem) and (orientation: portrait)
34
- color: white
35
-
@@ -1,16 +0,0 @@
1
- @use 'sass:meta'
2
- @use '../_misc-styling' as misc-styling
3
- @use '../../../node_modules/sass-true' as true
4
-
5
- @include true.test-module('Misc Styling')
6
- @include true.test('Applies background and text color')
7
- @include true.assert
8
- @include true.output
9
- .custom-bg
10
- @include misc-styling.background-color(rgb(255, 0, 0), rgb(255, 255, 255))
11
-
12
- @include true.expect
13
- .custom-bg
14
- color: rgba(255, 255, 255, 1)
15
- background-color: rgba(255, 0, 0, 1)
16
-
@@ -1,123 +0,0 @@
1
- @use 'sass:meta'
2
- @use '../_typography' as typo
3
- @use '../../../node_modules/sass-true' as true
4
-
5
- @include true.test-module('Typography')
6
- @include true.test('Generates font styles')
7
- @include true.assert
8
- @include true.output
9
- @include typo.font($size: 2rem, $weight: bold)
10
-
11
- @include true.expect
12
- font-size: 2rem
13
- font-weight: bold
14
-
15
- @include true.test('Generates sans-serif styles')
16
- @include true.assert
17
- @include true.output
18
- @include typo.sans-serif('Roboto', $size: 1.5rem)
19
-
20
- @include true.expect
21
- font-family: "Roboto", sans-serif
22
- font-size: 1.5rem
23
-
24
- @include true.test('Generates serif styles')
25
- @include true.assert
26
- @include true.output
27
- @include typo.serif('Georgia', $size: 1.2rem)
28
-
29
- @include true.expect
30
- font-family: "Georgia", serif
31
- font-size: 1.2rem
32
-
33
- @include true.test('Generates monospace styles')
34
- @include true.assert
35
- @include true.output
36
- @include typo.monospace('Fira Code', $weight: 500)
37
-
38
- @include true.expect
39
- font-family: "Fira Code", monospace
40
- font-size: 1rem
41
- font-weight: 500
42
-
43
- @include true.test('Returns correct font-family for known font')
44
- @include true.assert-equal(typo.font-family-of('Open Sans'), sans-serif)
45
-
46
- @include true.test('Detects generic category names')
47
- @include true.assert-equal(typo.font-family-of('mono'), monospace)
48
- @include true.assert-equal(typo.font-family-of('serif'), serif)
49
-
50
- @include true.test('Provides fallbacks for unknown fonts in font-family-of')
51
- @include true.assert-equal(typo.font-family-of('MyCustomFont'), ('Nunito', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif))
52
-
53
- @include true.test('Generates fallback for unknown font')
54
- @include true.assert
55
- @include true.output
56
- @include typo.font('MyCustomFont')
57
-
58
- @include true.expect
59
- font-family: "MyCustomFont", "Nunito", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
60
-
61
- @include true.test('Generates fallback for unknown font')
62
- @include true.assert
63
- @include true.output
64
- @include typo.font()
65
-
66
- @include true.expect
67
- font-family: "Nunito", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
68
-
69
- @include true.test('Does not overwrite explicit fallback override for unknown font')
70
- @include true.assert
71
- @include true.output
72
- @include typo.font('MyCustomFont', $family: serif)
73
-
74
- @include true.expect
75
- font-family: "MyCustomFont", serif
76
-
77
- @include true.test('Generates default fallback stack when no font is provided')
78
- @include true.assert
79
- @include true.output
80
- @include typo.font()
81
-
82
- @include true.expect
83
- font-family: "Nunito", Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
84
- font-size: 1rem
85
-
86
- @include true.test('Generates default system sans-serif stack when no font is provided')
87
- @include true.assert
88
- @include true.output
89
- @include typo.sans-serif()
90
-
91
- @include true.expect
92
- font-family: "Roboto", "Helvetica", "Arial", "Work Sans", "Nunito", "Open Sans", "Lato", "Montserrat", "Source Sans Pro", "Inter", "Tahoma", "Verdana", "Gill Sans", "Futura", "Ubuntu", "Noto Sans", "Noto Sans KR", "Noto Sans JP", "Noto Sans SC", "Noto Sans Arabic", "Noto Sans Hebrew", "Bootstrap", "bootstrap-icons", sans-serif
93
- font-size: 1rem
94
-
95
- @include true.test('Generates default system serif stack when no font is provided')
96
- @include true.assert
97
- @include true.output
98
- @include typo.serif()
99
-
100
- @include true.expect
101
- font-family: "Georgia", "Times New Roman", "Palatino", "Libre Baskerville", "Merriweather", "PT Serif", "Noto Serif", "Noto Serif KR", "Noto Serif JP", "Noto Serif SC", serif
102
- font-size: 1rem
103
-
104
- @include true.test('Generates default system monospace stack when no font is provided')
105
- @include true.assert
106
- @include true.output
107
- @include typo.monospace()
108
-
109
- @include true.expect
110
- font-family: "Courier New", "Consolas", "Ubuntu Mono", "Source Code Pro", "Fira Code", "Inconsolata", "Menlo", "Monaco", "Noto Mono", monospace
111
- font-size: 1rem
112
-
113
- @include true.test-module('Styling (Native)')
114
- @include true.test('Applies typography font styling to figcaption')
115
- @include true.assert
116
- @include true.output
117
- figure figcaption
118
- @include typo.font($style: italic)
119
-
120
- @include true.expect
121
- figure figcaption
122
- font-style: italic
123
-
@@ -1,11 +0,0 @@
1
- @use '../../node_modules/sass-true' as true
2
-
3
- // Import all colocated Sass tests here
4
- @use '../mix/test/media.spec'
5
- @use '../mix/test/buttons.spec'
6
- @use '../mix/test/elements.spec'
7
- @use '../mix/test/generators.spec'
8
- @use '../mix/test/typography.spec'
9
- @use '../mix/test/misc-styling.spec'
10
-
11
- @include true.report