@madj2k/fe-frontend-kit 2.0.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.
Files changed (40) hide show
  1. package/index.js +7 -0
  2. package/index.scss +6 -0
  3. package/menus/flyout-menu/flyout-menu-2.0.0.js +331 -0
  4. package/menus/flyout-menu/flyout-menu-2.0.0.scss +47 -0
  5. package/menus/flyout-menu/index.js +2 -0
  6. package/menus/flyout-menu/index.scss +1 -0
  7. package/menus/pulldown-menu/index.js +2 -0
  8. package/menus/pulldown-menu/index.scss +1 -0
  9. package/menus/pulldown-menu/pulldown-menu-2.0.0.js +196 -0
  10. package/menus/pulldown-menu/pulldown-menu-2.0.0.scss +33 -0
  11. package/package.json +31 -0
  12. package/readme.md +218 -0
  13. package/sass/bootstrap-5.3.0/00_mixins/_accessibility.scss +42 -0
  14. package/sass/bootstrap-5.3.0/00_mixins/_colors.scss +99 -0
  15. package/sass/bootstrap-5.3.0/00_mixins/_effects.scss +45 -0
  16. package/sass/bootstrap-5.3.0/00_mixins/_flex-box.scss +104 -0
  17. package/sass/bootstrap-5.3.0/00_mixins/_form.scss +164 -0
  18. package/sass/bootstrap-5.3.0/00_mixins/_format.scss +208 -0
  19. package/sass/bootstrap-5.3.0/00_mixins/_icons.scss +129 -0
  20. package/sass/bootstrap-5.3.0/00_mixins/_nav.scss +327 -0
  21. package/sass/bootstrap-5.3.0/00_mixins/_page.scss +261 -0
  22. package/sass/bootstrap-5.3.0/00_mixins/_section.scss +111 -0
  23. package/sass/bootstrap-5.3.0/00_mixins/_toggle-list.scss +133 -0
  24. package/sass/bootstrap-5.3.0/00_mixins/_unit.scss +51 -0
  25. package/sass/bootstrap-5.3.0/10_config/_colors.scss +17 -0
  26. package/sass/bootstrap-5.3.0/10_config/_font.scss +228 -0
  27. package/sass/bootstrap-5.3.0/10_config/_maps.scss +51 -0
  28. package/sass/bootstrap-5.3.0/index.scss +20 -0
  29. package/tools/owl/index.js +2 -0
  30. package/tools/owl/index.scss +1 -0
  31. package/tools/owl/owl-thumbnail-2.0.0.js +355 -0
  32. package/tools/owl/owl-thumbnail-2.0.0.scss +0 -0
  33. package/tools/resize-end/index.js +2 -0
  34. package/tools/resize-end/index.scss +1 -0
  35. package/tools/resize-end/resize-end-2.0.0.js +108 -0
  36. package/tools/resize-end/resize-end-2.0.0.scss +10 -0
  37. package/tools/scrolling/index.js +2 -0
  38. package/tools/scrolling/index.scss +1 -0
  39. package/tools/scrolling/scrolling-2.0.0.js +244 -0
  40. package/tools/scrolling/scrolling-2.0.0.scss +10 -0
package/readme.md ADDED
@@ -0,0 +1,218 @@
1
+ # @madj2k/frontend-kit
2
+ Reusable frontend toolkit including SCSS mixins and menu components (JS/SCSS).
3
+
4
+ # # Installation
5
+ ```
6
+ npm install @madj2k/frontend-kit
7
+ ```
8
+ Requirements:
9
+ For SCSS mixins: Bootstrap SCSS (your project needs to install bootstrap and include it in the build)
10
+ For menu components: none
11
+
12
+ ## Contains
13
+ * SASS mixins (using Bootstrap 5.3 functions/mixins)
14
+ * Menu components (JS + SCSS), Bootstrap-independent
15
+ * Several JS-Tools
16
+
17
+ ## Usage in your project
18
+ ### SCSS Mixins
19
+ ```
20
+ @use '@madj2k/frontend-kit' as *;
21
+ ```
22
+ Or import individual mixins:
23
+ ```
24
+ @use '@madj2k/frontend-kit/sass/00_mixins/colors' as *;
25
+ ```
26
+ ### Menu components (JS and SCSS):
27
+ Each menu component can be used separately.
28
+
29
+ # JS: Resize-End
30
+ A lightweight helper class that triggers a debounced 'madj2k-resize-end' event
31
+ when the user finishes resizing the browser window.
32
+
33
+ It also manages a scrolling detection state (via body attribute) to avoid triggering
34
+ resize-end during user scrolling, and respects active input fields (useful on mobile).
35
+
36
+ # JS: Scrolling
37
+ A lightweight scrolling helper class that enables:
38
+ 1. Body classes based on scroll direction (scroll-up / scroll-down)
39
+ 2. Smooth anchor scrolling with optional offset
40
+ 3. Automatic scrolling when collapsible elements (like Bootstrap .collapse) open
41
+ 4. Appear-on-scroll animations for elements
42
+
43
+ The class is fully configurable via options and is designed to be used in CMS contexts
44
+ where elements can be added, removed or re-ordered dynamically.
45
+
46
+ # JS: OWL-Thumbnails
47
+ A JavaScript helper class to create a main OWL carousel with a synchronized thumbnail navigation carousel.
48
+
49
+ Supports flexible configurations for both the main and the thumbnail carousels,
50
+ including:
51
+ - Custom navigation
52
+ - Syncing main carousel to clicked thumbnails
53
+ - Syncing thumbnails to main carousel changes
54
+ - Optionally equalizing thumbnail heights
55
+ - Optionally preventing the centered thumbnail stage shift (for designs where thumbs should stay left aligned)
56
+ - Responsive and CMS-friendly (works with dynamic content)
57
+
58
+ This is especially useful for image galleries or product carousels in CMS setups (e.g. TYPO3, WordPress, etc.)
59
+ where content may change dynamically.
60
+
61
+ # Flyout-Navigation
62
+ ## Usage
63
+ Integrate the CSS- and JS-file into your project. Make sure jQuery is included.
64
+ Then init the menu with
65
+ ```
66
+ import { Madj2kFlyoutMenu } from '@madj2k/frontend-kit/menus/flyout-menu';
67
+ document.querySelectorAll('.js-flyout-toggle').forEach((el) => {
68
+ new Madj2kFlyoutMenu(el, { animationDuration: 800 });
69
+ });
70
+ ```
71
+ CSS:
72
+ ```
73
+ @use '@madj2k/frontend-kit/menus/flyout-menu' as *;
74
+ ```
75
+
76
+ ## Basic HTML
77
+ ```
78
+ <div class="siteheader" id="siteheader">
79
+
80
+ [...]
81
+
82
+ <nav>
83
+ <button class="js-flyout-toggle"
84
+ aria-label="Open menu"
85
+ aria-controls="nav-mobile"
86
+ aria-haspopup="true"
87
+ aria-expanded="false">
88
+ <span class="icon-bars"></span>
89
+ </button>
90
+ <div class="flyout js-flyout"
91
+ id="nav-mobile"
92
+ data-position-ref="siteheader">
93
+ <div class="flyout-container js-flyout-container">
94
+ <div class="nav-mobile-inner js-flyout-inner">
95
+ CONTENT HERE
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </nav>
100
+ </div>
101
+ ```
102
+ IMPORTANT: If the siteheader is positioned with ```position:fixed```, you have to switch that to ```position:absolute``` when the menu is opened.
103
+ Otherwise in the opened menu the scrolling won't work.
104
+ ```
105
+ .flyout-open {
106
+ .siteheader {
107
+ position:absolute;
108
+ }
109
+ }
110
+ ```
111
+ ## Special: blur/gray effect for background
112
+ * In order to achieve a blur/gray-effect for the background we add the following DIV to the main-content section:
113
+ ```
114
+ <div class="background-blur"></div>
115
+ ```
116
+ Then we deactivate the fullHeight of the flyout menu and make the blurry background clickable
117
+ ```
118
+ import { Madj2kFlyoutdownMenu } from '@madj2k/frontend-kit/menus/flyout-menu';
119
+ document.querySelectorAll('.js-flyout-toggle').forEach((el) => {
120
+ new Madj2kFlyoutMenu(el, { fullHeight: false });
121
+ });
122
+ document.querySelector('.js-background-blur').addEventListener('click', function() {
123
+ document.dispatchEvent(new CustomEvent('madj2k-flyoutmenu-close'));
124
+ });
125
+ ```
126
+ * And we need this additional CSS:
127
+ ```
128
+ /**
129
+ * Prevent jumping because of scrollbar
130
+ */
131
+ html,body {
132
+ min-height: 100.1%;
133
+ }
134
+
135
+ /**
136
+ * background-blur for opened flyout
137
+ */
138
+ .background-blur {
139
+ position:fixed;
140
+ top:0;
141
+ left:0;
142
+ width: 100%;
143
+ height: 100%;
144
+ backdrop-filter: blur(1px) grayscale(100%);
145
+ background-color: rgba(255, 255, 255, 0.7);
146
+ transition: opacity 0.3s ease-in-out;
147
+ opacity:0;
148
+ z-index:-1;
149
+ }
150
+
151
+ .flyout-open,
152
+ .flyout-closing {
153
+ .background-blur {
154
+ z-index:90;
155
+ }
156
+ }
157
+
158
+ .flyout-open{
159
+ .background-blur {
160
+ opacity:1;
161
+ }
162
+ }
163
+
164
+
165
+ ```
166
+
167
+ # Pulldown-Navigation
168
+ ## Usage
169
+ Integrate the CSS- and JS-file into your project. Make sure jQuery is included.
170
+ Then init the menu with
171
+ ```
172
+ import { Madj2kPulldownMenu } from '@madj2k/frontend-kit/menus/pulldown-menu';
173
+ document.querySelectorAll('.js-pulldown-toggle').forEach((el) => {
174
+ new Madj2kPulldownMenu(el);
175
+ });
176
+ ```
177
+ CSS:
178
+ ```
179
+ @use '@madj2k/frontend-kit/menus/pulldown-menu' as *;
180
+ ```
181
+
182
+ ## Basic HTML
183
+ ```
184
+ <div class="siteheader">
185
+
186
+ [...]
187
+
188
+ <nav class="pulldown-wrap js-pulldown-wrap">
189
+ <button class="pulldown-toggle js-pulldown-toggle"
190
+ aria-label="Open Menu"
191
+ aria-controls="nav-language"
192
+ aria-haspopup="true"
193
+ aria-expanded="false">
194
+ <span>Menu-Item Level 1</span>
195
+ </button>
196
+
197
+ <div class="pulldown js-pulldown" id="nav-language">
198
+ <div class="pulldown-inner">
199
+ <ul>
200
+ <!-- used to have the right padding-top of the pulldown -->
201
+ <li class="pulldown-hide">
202
+ <a href="#" tabIndex="-1"><span>Menu-Item Level 1</span></a>
203
+ </li>
204
+ <li>
205
+ <a href="#"><span>Menu-Item I Level 2</span></a>
206
+ </li>
207
+ <li>
208
+ <a href="#"><span>Menu-Item II Level 2</span></a>
209
+ </li>
210
+ <li>
211
+ ...
212
+ </li>
213
+ </ul>
214
+ </div>
215
+ </div>
216
+ </nav>
217
+ </div>
218
+ ```
@@ -0,0 +1,42 @@
1
+ /* ==================================================
2
+ * Accessibility
3
+ * ================================================== */
4
+ /// Adds a visible and accessible focus outline for interactive elements.
5
+ ///
6
+ /// Ensures that keyboard users can visually identify focused elements
7
+ /// (e.g., buttons, links, inputs) with a strong outline for accessibility.
8
+ /// This mixin is meant to be used on elements that need clear focus styles
9
+ /// without relying on default browser outlines.
10
+ ///
11
+ /// @group Accessibility
12
+ ///
13
+ /// @param {Color} $color - Outline color for focused state. Defaults to `$color-outline`.
14
+ /// @param {Length} $width - Outline width. Defaults to `3px`.
15
+ ///
16
+ /// @example scss
17
+ /// button,
18
+ /// a {
19
+ /// @include accessibility-outline();
20
+ /// }
21
+ ///
22
+ /// @example scss
23
+ /// .custom-button {
24
+ /// @include accessibility-outline($color: #005fcc, $width: 2px);
25
+ /// }
26
+ ///
27
+ /// @author Steffen Kroggel <developer@steffenkroggel>
28
+ /// @license GNU General Public License v3.0 https://www.gnu.org/licenses/gpl-3.0.en.html
29
+ ///
30
+ @mixin accessibility-outline ($color: $color-outline, $width: 3px) {
31
+
32
+ &:focus,
33
+ &:focus-within {
34
+ outline: 0;
35
+ }
36
+
37
+ &:has(input:focus-visible),
38
+ &:focus-visible {
39
+ outline: rem-calc($width) solid $color;
40
+ }
41
+
42
+ }
@@ -0,0 +1,99 @@
1
+ /// Generates utility classes for background colors based on a Sass map.
2
+ ///
3
+ /// For each key–value pair in the provided map, a class with a suffix of `-<key>`
4
+ /// is created, setting `background-color` to the mapped value.
5
+ ///
6
+ /// Typically used in component systems or design tokens to expose theme colors.
7
+ ///
8
+ /// @group Utilities
9
+ ///
10
+ /// @param {Map} $map - A Sass map of color names and values (e.g. `("primary": #005fcc, "secondary": #999)`). Defaults to `$color-map`.
11
+ ///
12
+ /// @example scss
13
+ /// @include background-color-classes((
14
+ /// "primary": #005fcc,
15
+ /// "secondary": #999,
16
+ /// "light": #f5f5f5
17
+ /// ));
18
+ ///
19
+ /// @example css
20
+ /// .bg-primary { background-color: #005fcc; }
21
+ /// .bg-secondary { background-color: #999; }
22
+ ///
23
+ /// @author Steffen Kroggel <developer@steffenkroggel>
24
+ /// @license GNU General Public License v3.0 https://www.gnu.org/licenses/gpl-3.0.en.html
25
+ ///
26
+ @mixin background-color-classes($map: $color-map) {
27
+ @each $key, $value in $map {
28
+ &-#{$key} {
29
+ background-color: $value;
30
+ }
31
+
32
+ @each $breakpoint, $size in $grid-breakpoints {
33
+ @media (min-width: $size) {
34
+ &-#{$breakpoint}-#{$key} {
35
+ background-color: $value;
36
+ }
37
+
38
+ &-#{$breakpoint}-none {
39
+ background-color: transparent;
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ /// Generates utility classes for text color based on a Sass map.
47
+ ///
48
+ /// For each key–value pair in the provided map, a class with a suffix of `-<key>`
49
+ /// is created, setting the `color` of the element and its immediate children to the mapped value.
50
+ ///
51
+ /// Adds `!important` to ensure style application even when overridden.
52
+ ///
53
+ /// @group Utilities
54
+ ///
55
+ /// @param {Map} $map - A Sass map of color names and values. Defaults to `$color-map`.
56
+ ///
57
+ /// @example scss
58
+ /// @include font-color-classes((
59
+ /// "danger": #e00,
60
+ /// "success": #0a0
61
+ /// ));
62
+ ///
63
+ /// @example css
64
+ /// .text-danger { color: #e00 !important; }
65
+ /// .text-danger > * { color: #e00 !important; }
66
+ ///
67
+ /// @author Steffen Kroggel <developer@steffenkroggel>
68
+ /// @license GNU General Public License v3.0 https://www.gnu.org/licenses/gpl-3.0.en.html
69
+ ///
70
+ @mixin font-color-classes($map: $color-map) {
71
+ @each $key, $value in $map {
72
+ &-#{$key} {
73
+ color: $value !important;
74
+
75
+ & > * {
76
+ color: $value !important;
77
+ }
78
+ }
79
+ @each $breakpoint, $size in $grid-breakpoints {
80
+ @media (min-width: $size) {
81
+ &-#{$breakpoint}-#{$key} {
82
+ color: $value !important;
83
+
84
+ & > * {
85
+ color: $value !important;
86
+ }
87
+ }
88
+
89
+ &-#{$breakpoint}-none {
90
+ color: inherit !important;
91
+
92
+ & > * {
93
+ color: inherit !important;
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
@@ -0,0 +1,45 @@
1
+ /// Adds a custom underline to text elements using a pseudo-element.
2
+ ///
3
+ /// This mixin creates a visual underline using `::after`, which allows
4
+ /// for more control than `text-decoration`. It supports customizable
5
+ /// color and thickness, and adjusts vertical spacing responsively.
6
+ ///
7
+ /// Useful for link-like text styling or emphasis elements.
8
+ ///
9
+ /// @group Effects
10
+ ///
11
+ /// @param {Color} $color - The underline color. Default: `$color-primary`.
12
+ /// @param {Length} $width - Thickness of the underline (in px, converted to `rem`). Default: `2px`.
13
+ ///
14
+ /// @example scss
15
+ /// .highlighted-text {
16
+ /// @include underline($color-tertiary, 3px);
17
+ /// }
18
+ ///
19
+ /// @example css
20
+ /// .highlighted-text::after {
21
+ /// border-bottom: 0.1875rem solid #cc0000;
22
+ /// bottom: -0.09em;
23
+ /// }
24
+ ///
25
+ /// @author Steffen Kroggel <developer@steffenkroggel>
26
+ /// @license GNU General Public License v3.0 https://www.gnu.org/licenses/gpl-3.0.en.html
27
+ ///
28
+ @mixin underline ($color: $color-primary, $width: 2px) {
29
+
30
+ position: relative;
31
+ display: inline-block;
32
+
33
+ &::after {
34
+ content: '';
35
+ position: absolute;
36
+ left: 0;
37
+ right: 0;
38
+ bottom: -0.09em;
39
+ border-bottom: rem-calc($width) solid $color;
40
+
41
+ @include media-breakpoint-up(xl) {
42
+ bottom: -0.15em;
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,104 @@
1
+ /// Calculates `flex-basis` for a given number of columns while accounting for CSS `gap`.
2
+ ///
3
+ /// This mixin ensures that items within a flex container evenly divide available width,
4
+ /// **including** the horizontal `gap` spacing between them.
5
+ /// Ideal for grid-like layouts using `display: flex` and `gap`.
6
+ ///
7
+ /// Based on: https://stackoverflow.com/questions/72116170/account-for-gap-when-calculating-flex-basis
8
+ ///
9
+ /// @group Layout
10
+ ///
11
+ /// @param {Number} $cols - Number of columns (flex items per row). Default: `2`.
12
+ /// @param {Length} $gap - Horizontal gap between items. Default: `16px`.
13
+ /// @return {Declaration} - Sets `flex-basis` using a `calc()` formula.
14
+ ///
15
+ /// @example scss
16
+ /// .grid-item {
17
+ /// @include flex-basis(3, 24px);
18
+ /// }
19
+ ///
20
+ /// @example css
21
+ /// flex-basis: calc(100% / 3 - 24px / 3 * (3 - 1));
22
+ ///
23
+ /// @author Steffen Kroggel <developer@steffenkroggel>
24
+ /// @license GNU General Public License v3.0 https://www.gnu.org/licenses/gpl-3.0.en.html
25
+ ///
26
+ @mixin flex-basis($cols: 2, $gap: 16px) {
27
+ flex-basis: calc(100% / #{$cols} - #{$gap} / #{$cols} * (#{$cols} - 1));
28
+ }
29
+
30
+
31
+ /// Flexbox Item Width Generator
32
+ ///
33
+ /// Dynamically generates responsive flex item widths based on the number
34
+ /// of items in a container and a column-count configuration map.
35
+ ///
36
+ /// This mixin assumes that item widths are calculated using a helper mixin
37
+ /// like `@include flex-basis($columns, $gap)` which distributes space based
38
+ /// on a total column count per row, adjusted for a given gap.
39
+ ///
40
+ /// @param {Map} $config - A map where:
41
+ /// - Keys are the total number of items in a row (e.g., 4, 5, 6)
42
+ /// - Values are either:
43
+ /// - A single number: the number of columns for that layout
44
+ /// - A map of item index ranges (e.g., `'1-3'`, `'4-5'`) where each
45
+ /// range defines how many columns those items span in that row
46
+ ///
47
+ /// @param {Length} $gap - Optional spacing between columns (default: `0`)
48
+ ///
49
+ /// @param {String} $counterClassPrefix - The base class prefix for the container,
50
+ /// e.g. '.items' or '.grid--cols' (default: '.items').
51
+ ///
52
+ /// @param {String} $className - The selector for each item (default: '.item')
53
+ ///
54
+ /// @example scss - Uniform layout
55
+ /// $layout: (
56
+ /// 4: 2, // All 4 items arranged in 2 columns (2 per row)
57
+ /// 6: 3 // All 6 items in 3 columns
58
+ /// );
59
+ ///
60
+ /// @example scss - Mixed layout with row-specific splits
61
+ /// $layout: (
62
+ /// 5: (
63
+ /// '1-3': 3, // First row: 3 columns (items 1–3)
64
+ /// '4-5': 2 // Second row: 2 columns (items 4–5)
65
+ /// )
66
+ /// );
67
+ ///
68
+ /// @output
69
+ /// Generates selectors like `.items-5 .item:nth-child(...)` with flex-basis
70
+ /// calculated using the number of columns and the provided gap.
71
+ ///
72
+ /// @note
73
+ /// This mixin requires a `flex-basis($columns, $gap)` helper mixin or function
74
+ /// that performs the actual width calculation (e.g., using `calc(...)`)
75
+ ///
76
+ /// @author Steffen Kroggel <developer@steffenkroggel>
77
+ /// @license GNU General Public License v3.0 https://www.gnu.org/licenses/gpl-3.0.en.html
78
+ ///
79
+ @mixin flex-basis-dynamically($config, $gap: 0, $counterClassPrefix: '.count', $className: '.item') {
80
+ @each $count, $value in $config {
81
+ @if type-of($value) == "map" {
82
+ @each $range, $columns in $value {
83
+ $start: null;
84
+ $end: null;
85
+
86
+ @if str-index($range, '-') != null {
87
+ $start: str-slice($range, 1, str-index($range, '-') - 1);
88
+ $end: str-slice($range, str-index($range, '-') + 1);
89
+ } @else {
90
+ $start: $range;
91
+ $end: $range;
92
+ }
93
+
94
+ #{$counterClassPrefix}-#{$count} #{$className}:nth-child(n+#{$start}):nth-child(-n+#{$end}) {
95
+ @include flex-basis($columns, $gap);
96
+ }
97
+ }
98
+ } @else {
99
+ #{$counterClassPrefix}-#{$count} #{$className} {
100
+ @include flex-basis($value, $gap);
101
+ }
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,164 @@
1
+ /**! ==================================================
2
+ * Mixin form fields
3
+ * ================================================== */
4
+ @use 'sass:math';
5
+
6
+ /// Styles a custom checkbox input field with accessible markup and visual feedback.
7
+ ///
8
+ /// Adds support for background and border color customization, as well as custom icons for
9
+ /// default and active states.
10
+ ///
11
+ /// @group Form Fields
12
+ ///
13
+ /// @param {Length} $size - The visual size of the checkbox element. Default: `16px`.
14
+ /// @param {Color} $default-bg-color - Background color for default state.
15
+ /// @param {Color} $default-border-color - Border color for default state.
16
+ /// @param {String} $default-icon - Icon shown in default state (optional).
17
+ /// @param {Color} $active-bg-color - Background color for checked/active state.
18
+ /// @param {Color} $active-border-color - Border color for checked/active state.
19
+ /// @param {String} $active-icon - Icon shown when checkbox is checked.
20
+ ///
21
+ /// @example scss
22
+ /// .form-check-field:has(input[type="checkbox"]) {
23
+ /// @include checkbox();
24
+ /// }
25
+ ///
26
+ /// @example html
27
+ /// <label class="form-check-label" for="element-1">
28
+ /// <span class="form-check-field">
29
+ /// <input class="checkbox" id="element-1" type="checkbox" name="" value="1">
30
+ /// </span>
31
+ /// <span>Label</span>
32
+ /// </label>
33
+ ///
34
+ /// @author
35
+ /// Steffen Kroggel <developer@steffenkroggel>
36
+ ///
37
+ /// @license
38
+ /// GNU General Public License v3.0 https://www.gnu.org/licenses/gpl-3.0.en.html
39
+ ///
40
+ @mixin checkbox(
41
+ $size: 16px,
42
+ $default-bg-color: $color-white,
43
+ $default-border-color: $color-secondary,
44
+ $default-icon: null,
45
+ $active-bg-color: $color-primary,
46
+ $active-border-color: $color-primary,
47
+ $active-icon: '../Images/input-checkbox-active.svg'
48
+ ) {
49
+ position: relative;
50
+ display: inline;
51
+ padding-left: rem-calc(math.ceil(strip-unit($size) * 2 * 0.8));
52
+
53
+ input {
54
+ position: absolute;
55
+ width: 1em;
56
+ height: 1em;
57
+ left: 0;
58
+ opacity: 0;
59
+ }
60
+
61
+ @include accessibility-outline();
62
+
63
+ &::before {
64
+ content: "";
65
+ position: absolute;
66
+ left: rem-calc(0);
67
+ display: inline-block;
68
+ width: rem-calc($size);
69
+ height: rem-calc($size);
70
+ border: rem-calc(1) solid $default-border-color;
71
+ margin-top: rem-calc(-3);
72
+ margin-right: rem-calc(10);
73
+ background-color: $default-bg-color;
74
+ background-size: 100%;
75
+ transform: translateY(4px);
76
+ border-radius: rem-calc(4);
77
+
78
+ @if $default-icon != null {
79
+ background-image: url(#{$default-icon});
80
+ background-repeat: no-repeat;
81
+ background-position: center;
82
+ background-size: rem-calc(math.ceil(strip-unit($size) * 0.75));
83
+ }
84
+ }
85
+
86
+ &:has(input:checked),
87
+ &[aria-selected="true"] {
88
+ &::before {
89
+ background-color: $active-bg-color;
90
+ border-color: $active-border-color;
91
+ background-image: url(#{$active-icon});
92
+ background-repeat: no-repeat;
93
+ background-position: center;
94
+ background-size: rem-calc(math.ceil(strip-unit($size) * 0.75));
95
+ }
96
+ }
97
+ }
98
+
99
+
100
+ /// Styles a custom radio input field based on the checkbox mixin.
101
+ ///
102
+ /// Builds on the `checkbox()` structure, but renders a circular selection element.
103
+ /// Supports separate border/background/icon definitions for both default and checked state.
104
+ ///
105
+ /// @group Form Fields
106
+ ///
107
+ /// @param {Length} $size - The visual size of the radio element. Default: `16px`.
108
+ /// @param {Color} $default-bg-color - Background color for default state.
109
+ /// @param {Color} $default-border-color - Border color for default state.
110
+ /// @param {String} $default-icon - Icon shown when radio is not selected (optional).
111
+ /// @param {Color} $active-bg-color - Background color for selected state.
112
+ /// @param {Color} $active-border-color - Border color for selected state.
113
+ /// @param {String} $active-icon - Icon shown when radio is selected.
114
+ ///
115
+ /// @example scss
116
+ /// .form-check-field:has(input[type="radio"]) {
117
+ /// @include radio();
118
+ /// }
119
+ ///
120
+ /// @example html
121
+ /// <label class="form-check-label" for="element-2">
122
+ /// <span class="form-check-field">
123
+ /// <input class="radio" id="element-2" type="radio" name="options" value="2">
124
+ /// </span>
125
+ /// <span>Label</span>
126
+ /// </label>
127
+ ///
128
+ /// @author
129
+ /// Steffen Kroggel <developer@steffenkroggel>
130
+ ///
131
+ /// @license
132
+ /// GNU General Public License v3.0 https://www.gnu.org/licenses/gpl-3.0.en.html
133
+ ///
134
+ @mixin radio(
135
+ $size: 16px,
136
+ $default-bg-color: $color-white,
137
+ $default-border-color: $color-secondary,
138
+ $default-icon: null,
139
+ $active-bg-color: $color-primary,
140
+ $active-border-color: $color-primary,
141
+ $active-icon: '../Images/input-radio-active.svg'
142
+ ) {
143
+ @include checkbox(
144
+ $size,
145
+ $default-bg-color,
146
+ $default-border-color,
147
+ $default-icon,
148
+ $active-bg-color,
149
+ $active-border-color,
150
+ $active-icon
151
+ );
152
+
153
+ &::before {
154
+ border-radius: rem-calc($size); // circular shape
155
+ }
156
+
157
+ &:has(input:checked),
158
+ &[aria-selected="true"] {
159
+ &::before {
160
+ border: 0;
161
+ background-size: rem-calc(math.ceil(strip-unit($size) * 0.5));
162
+ }
163
+ }
164
+ }