@rhavenside/baseline-ui 1.0.1 → 1.0.3
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 +51 -0
- package/dist/baseline.css +144 -14
- package/dist/baseline.css.map +1 -1
- package/dist/baseline.js +193 -0
- package/dist/baseline.js.map +7 -0
- package/dist/baseline.min.css +1 -1
- package/dist/baseline.min.js +2 -0
- package/dist/baseline.min.js.map +7 -0
- package/package.json +14 -12
- package/src/components/_card.scss +6 -10
- package/src/components/_dropdown.scss +4 -1
- package/src/components/_form.scss +157 -6
- package/src/js/baseline.js +59 -0
- package/src/js/components/alert.js +25 -0
- package/src/js/components/dropdown.js +40 -0
- package/src/js/components/modal.js +67 -0
- package/src/js/components/tabs.js +49 -0
- package/src/js/components/tooltip.js +37 -0
- package/src/tokens/_z-index.scss +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/js/components/modal.js", "../src/js/components/dropdown.js", "../src/js/components/tooltip.js", "../src/js/components/tabs.js", "../src/js/components/alert.js", "../src/js/baseline.js"],
|
|
4
|
+
"sourcesContent": ["// ============================================================================\n// Modal Component JavaScript\n// ============================================================================\n\nexport function initModal(modalElement) {\n if (!modalElement) return;\n\n const backdrop = modalElement.querySelector('.bl-modal-backdrop') || document.createElement('div');\n if (!backdrop.classList.contains('bl-modal-backdrop')) {\n backdrop.className = 'bl-modal-backdrop';\n modalElement.insertBefore(backdrop, modalElement.firstChild);\n }\n\n // Open modal buttons\n const modalId = modalElement.id;\n if (modalId) {\n const openButtons = document.querySelectorAll(`[data-modal-open=\"${modalId}\"]`);\n openButtons.forEach(btn => {\n btn.addEventListener('click', () => {\n openModal(modalId);\n });\n });\n }\n\n // Close modal buttons\n const closeButtons = modalElement.querySelectorAll('.bl-modal-close, [data-modal-close]');\n closeButtons.forEach(btn => {\n btn.addEventListener('click', () => {\n closeModal(modalId);\n });\n });\n\n // Close on backdrop click\n backdrop.addEventListener('click', (e) => {\n if (e.target === backdrop) {\n closeModal(modalId);\n }\n });\n\n // Close on ESC key\n const escHandler = (e) => {\n if (e.key === 'Escape' && modalElement.style.display === 'block') {\n closeModal(modalId);\n }\n };\n document.addEventListener('keydown', escHandler);\n \n // Store handler for cleanup if needed\n modalElement._escHandler = escHandler;\n}\n\nexport function openModal(modalId) {\n const modal = document.getElementById(modalId);\n if (modal) {\n modal.style.display = 'block';\n document.body.style.overflow = 'hidden';\n }\n}\n\nexport function closeModal(modalId) {\n const modal = document.getElementById(modalId);\n if (modal) {\n modal.style.display = 'none';\n document.body.style.overflow = '';\n }\n}\n\n", "// ============================================================================\n// Dropdown Component JavaScript\n// ============================================================================\n\nexport function initDropdown(dropdownElement) {\n if (!dropdownElement) return;\n\n const toggle = dropdownElement.querySelector('.bl-dropdown-toggle');\n const menu = dropdownElement.querySelector('.bl-dropdown-menu');\n\n if (!toggle || !menu) return;\n\n toggle.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n // Close all other dropdowns\n document.querySelectorAll('.bl-dropdown-menu.bl-show').forEach(otherMenu => {\n if (otherMenu !== menu) {\n otherMenu.classList.remove('bl-show');\n }\n });\n\n // Toggle current dropdown\n menu.classList.toggle('bl-show');\n });\n\n // Close on outside click\n const outsideClickHandler = (e) => {\n if (!dropdownElement.contains(e.target)) {\n menu.classList.remove('bl-show');\n }\n };\n \n document.addEventListener('click', outsideClickHandler);\n \n // Store handler for cleanup if needed\n dropdownElement._outsideClickHandler = outsideClickHandler;\n}\n\n", "// ============================================================================\n// Tooltip Component JavaScript\n// ============================================================================\n\nexport function initTooltip(tooltipElement) {\n if (!tooltipElement) return;\n\n const trigger = tooltipElement.querySelector('.bl-tooltip-trigger');\n const content = tooltipElement.querySelector('.bl-tooltip-content');\n\n if (!trigger || !content) {\n console.warn('Baseline UI: Tooltip missing trigger or content', tooltipElement);\n return;\n }\n\n // Skip if already initialized\n if (trigger._tooltipInitialized) return;\n\n // Create handlers\n const enterHandler = () => {\n content.classList.add('bl-show');\n };\n\n const leaveHandler = () => {\n content.classList.remove('bl-show');\n };\n\n // Add event listeners\n trigger.addEventListener('mouseenter', enterHandler);\n trigger.addEventListener('mouseleave', leaveHandler);\n\n // Mark as initialized\n trigger._tooltipInitialized = true;\n trigger._tooltipEnterHandler = enterHandler;\n trigger._tooltipLeaveHandler = leaveHandler;\n}\n\n", "// ============================================================================\n// Tabs Component JavaScript\n// ============================================================================\n\nexport function initTabs(tabsContainer) {\n if (!tabsContainer) return;\n\n const tabLinks = tabsContainer.querySelectorAll('.bl-nav-link[data-tab-target]');\n const tabGroup = tabsContainer.getAttribute('data-tab-group');\n\n tabLinks.forEach(link => {\n link.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Remove active from all tabs in group\n if (tabGroup) {\n document.querySelectorAll(`[data-tab-group=\"${tabGroup}\"] .bl-nav-link`).forEach(l => {\n l.classList.remove('bl-active');\n });\n } else {\n tabsContainer.querySelectorAll('.bl-nav-link').forEach(l => {\n l.classList.remove('bl-active');\n });\n }\n\n // Add active to clicked tab\n link.classList.add('bl-active');\n\n // Show/hide tab content\n const targetId = link.getAttribute('data-tab-target');\n if (targetId) {\n // Find all tab contents - search in parent container or document\n const container = tabsContainer.closest('.docs-example-preview') || \n tabsContainer.parentElement || \n document;\n \n container.querySelectorAll('[data-tab-content]').forEach(content => {\n content.style.display = 'none';\n });\n\n const targetContent = document.getElementById(targetId);\n if (targetContent) {\n targetContent.style.display = 'block';\n }\n }\n });\n });\n}\n\n", "// ============================================================================\n// Alert Component JavaScript\n// ============================================================================\n\nexport function initAlert(alertElement) {\n if (!alertElement) return;\n\n const closeBtn = alertElement.querySelector('.bl-alert-close');\n if (!closeBtn) return;\n\n closeBtn.addEventListener('click', () => {\n dismissAlert(alertElement);\n });\n}\n\nexport function dismissAlert(alertElement) {\n if (!alertElement) return;\n \n alertElement.style.transition = 'opacity 0.3s ease-out';\n alertElement.style.opacity = '0';\n setTimeout(() => {\n alertElement.remove();\n }, 300);\n}\n\n", "// ============================================================================\n// Baseline UI JavaScript\n// Main Entry Point\n// ============================================================================\n\nimport { initModal, openModal, closeModal } from './components/modal.js';\nimport { initDropdown } from './components/dropdown.js';\nimport { initTooltip } from './components/tooltip.js';\nimport { initTabs } from './components/tabs.js';\nimport { initAlert, dismissAlert } from './components/alert.js';\n\n// Export all functions for manual use\nexport {\n initModal,\n openModal,\n closeModal,\n initDropdown,\n initTooltip,\n initTabs,\n initAlert,\n dismissAlert\n};\n\n// Auto-initialize on DOM ready\nfunction autoInit() {\n // Initialize all modals\n document.querySelectorAll('.bl-modal').forEach(modal => {\n initModal(modal);\n });\n\n // Initialize all dropdowns\n document.querySelectorAll('.bl-dropdown').forEach(dropdown => {\n initDropdown(dropdown);\n });\n\n // Initialize all tooltips\n document.querySelectorAll('.bl-tooltip').forEach(tooltip => {\n initTooltip(tooltip);\n });\n\n // Initialize all tabs\n document.querySelectorAll('.bl-nav-tabs').forEach(tabs => {\n initTabs(tabs);\n });\n\n // Initialize all dismissible alerts\n document.querySelectorAll('.bl-alert-dismissible').forEach(alert => {\n initAlert(alert);\n });\n}\n\n// Initialize when DOM is ready\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', autoInit);\n} else {\n // Use setTimeout to ensure DOM is fully ready\n setTimeout(autoInit, 0);\n}\n\n"],
|
|
5
|
+
"mappings": "AAIO,SAASA,EAAUC,EAAc,CACtC,GAAI,CAACA,EAAc,OAEnB,IAAMC,EAAWD,EAAa,cAAc,oBAAoB,GAAK,SAAS,cAAc,KAAK,EAC5FC,EAAS,UAAU,SAAS,mBAAmB,IAClDA,EAAS,UAAY,oBACrBD,EAAa,aAAaC,EAAUD,EAAa,UAAU,GAI7D,IAAME,EAAUF,EAAa,GACzBE,GACkB,SAAS,iBAAiB,qBAAqBA,CAAO,IAAI,EAClE,QAAQC,GAAO,CACzBA,EAAI,iBAAiB,QAAS,IAAM,CAClCC,EAAUF,CAAO,CACnB,CAAC,CACH,CAAC,EAIkBF,EAAa,iBAAiB,qCAAqC,EAC3E,QAAQG,GAAO,CAC1BA,EAAI,iBAAiB,QAAS,IAAM,CAClCE,EAAWH,CAAO,CACpB,CAAC,CACH,CAAC,EAGDD,EAAS,iBAAiB,QAAUK,GAAM,CACpCA,EAAE,SAAWL,GACfI,EAAWH,CAAO,CAEtB,CAAC,EAGD,IAAMK,EAAcD,GAAM,CACpBA,EAAE,MAAQ,UAAYN,EAAa,MAAM,UAAY,SACvDK,EAAWH,CAAO,CAEtB,EACA,SAAS,iBAAiB,UAAWK,CAAU,EAG/CP,EAAa,YAAcO,CAC7B,CAEO,SAASH,EAAUF,EAAS,CACjC,IAAMM,EAAQ,SAAS,eAAeN,CAAO,EACzCM,IACFA,EAAM,MAAM,QAAU,QACtB,SAAS,KAAK,MAAM,SAAW,SAEnC,CAEO,SAASH,EAAWH,EAAS,CAClC,IAAMM,EAAQ,SAAS,eAAeN,CAAO,EACzCM,IACFA,EAAM,MAAM,QAAU,OACtB,SAAS,KAAK,MAAM,SAAW,GAEnC,CC7DO,SAASC,EAAaC,EAAiB,CAC5C,GAAI,CAACA,EAAiB,OAEtB,IAAMC,EAASD,EAAgB,cAAc,qBAAqB,EAC5DE,EAAOF,EAAgB,cAAc,mBAAmB,EAE9D,GAAI,CAACC,GAAU,CAACC,EAAM,OAEtBD,EAAO,iBAAiB,QAAUE,GAAM,CACtCA,EAAE,eAAe,EACjBA,EAAE,gBAAgB,EAGlB,SAAS,iBAAiB,2BAA2B,EAAE,QAAQC,GAAa,CACtEA,IAAcF,GAChBE,EAAU,UAAU,OAAO,SAAS,CAExC,CAAC,EAGDF,EAAK,UAAU,OAAO,SAAS,CACjC,CAAC,EAGD,IAAMG,EAAuBF,GAAM,CAC5BH,EAAgB,SAASG,EAAE,MAAM,GACpCD,EAAK,UAAU,OAAO,SAAS,CAEnC,EAEA,SAAS,iBAAiB,QAASG,CAAmB,EAGtDL,EAAgB,qBAAuBK,CACzC,CClCO,SAASC,EAAYC,EAAgB,CAC1C,GAAI,CAACA,EAAgB,OAErB,IAAMC,EAAUD,EAAe,cAAc,qBAAqB,EAC5DE,EAAUF,EAAe,cAAc,qBAAqB,EAElE,GAAI,CAACC,GAAW,CAACC,EAAS,CACxB,QAAQ,KAAK,kDAAmDF,CAAc,EAC9E,MACF,CAGA,GAAIC,EAAQ,oBAAqB,OAGjC,IAAME,EAAe,IAAM,CACzBD,EAAQ,UAAU,IAAI,SAAS,CACjC,EAEME,EAAe,IAAM,CACzBF,EAAQ,UAAU,OAAO,SAAS,CACpC,EAGAD,EAAQ,iBAAiB,aAAcE,CAAY,EACnDF,EAAQ,iBAAiB,aAAcG,CAAY,EAGnDH,EAAQ,oBAAsB,GAC9BA,EAAQ,qBAAuBE,EAC/BF,EAAQ,qBAAuBG,CACjC,CC/BO,SAASC,EAASC,EAAe,CACtC,GAAI,CAACA,EAAe,OAEpB,IAAMC,EAAWD,EAAc,iBAAiB,+BAA+B,EACzEE,EAAWF,EAAc,aAAa,gBAAgB,EAE5DC,EAAS,QAAQE,GAAQ,CACvBA,EAAK,iBAAiB,QAAUC,GAAM,CACpCA,EAAE,eAAe,EAGbF,EACF,SAAS,iBAAiB,oBAAoBA,CAAQ,iBAAiB,EAAE,QAAQG,GAAK,CACpFA,EAAE,UAAU,OAAO,WAAW,CAChC,CAAC,EAEDL,EAAc,iBAAiB,cAAc,EAAE,QAAQK,GAAK,CAC1DA,EAAE,UAAU,OAAO,WAAW,CAChC,CAAC,EAIHF,EAAK,UAAU,IAAI,WAAW,EAG9B,IAAMG,EAAWH,EAAK,aAAa,iBAAiB,EACpD,GAAIG,EAAU,EAEMN,EAAc,QAAQ,uBAAuB,GAC9CA,EAAc,eACd,UAEP,iBAAiB,oBAAoB,EAAE,QAAQO,GAAW,CAClEA,EAAQ,MAAM,QAAU,MAC1B,CAAC,EAED,IAAMC,EAAgB,SAAS,eAAeF,CAAQ,EAClDE,IACFA,EAAc,MAAM,QAAU,QAElC,CACF,CAAC,CACH,CAAC,CACH,CC3CO,SAASC,EAAUC,EAAc,CACtC,GAAI,CAACA,EAAc,OAEnB,IAAMC,EAAWD,EAAa,cAAc,iBAAiB,EACxDC,GAELA,EAAS,iBAAiB,QAAS,IAAM,CACvCC,EAAaF,CAAY,CAC3B,CAAC,CACH,CAEO,SAASE,EAAaF,EAAc,CACpCA,IAELA,EAAa,MAAM,WAAa,wBAChCA,EAAa,MAAM,QAAU,IAC7B,WAAW,IAAM,CACfA,EAAa,OAAO,CACtB,EAAG,GAAG,EACR,CCCA,SAASG,GAAW,CAElB,SAAS,iBAAiB,WAAW,EAAE,QAAQC,GAAS,CACtDC,EAAUD,CAAK,CACjB,CAAC,EAGD,SAAS,iBAAiB,cAAc,EAAE,QAAQE,GAAY,CAC5DC,EAAaD,CAAQ,CACvB,CAAC,EAGD,SAAS,iBAAiB,aAAa,EAAE,QAAQE,GAAW,CAC1DC,EAAYD,CAAO,CACrB,CAAC,EAGD,SAAS,iBAAiB,cAAc,EAAE,QAAQE,GAAQ,CACxDC,EAASD,CAAI,CACf,CAAC,EAGD,SAAS,iBAAiB,uBAAuB,EAAE,QAAQE,GAAS,CAClEC,EAAUD,CAAK,CACjB,CAAC,CACH,CAGI,SAAS,aAAe,UAC1B,SAAS,iBAAiB,mBAAoBT,CAAQ,EAGtD,WAAWA,EAAU,CAAC",
|
|
6
|
+
"names": ["initModal", "modalElement", "backdrop", "modalId", "btn", "openModal", "closeModal", "e", "escHandler", "modal", "initDropdown", "dropdownElement", "toggle", "menu", "e", "otherMenu", "outsideClickHandler", "initTooltip", "tooltipElement", "trigger", "content", "enterHandler", "leaveHandler", "initTabs", "tabsContainer", "tabLinks", "tabGroup", "link", "e", "l", "targetId", "content", "targetContent", "initAlert", "alertElement", "closeBtn", "dismissAlert", "autoInit", "modal", "initModal", "dropdown", "initDropdown", "tooltip", "initTooltip", "tabs", "initTabs", "alert", "initAlert"]
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhavenside/baseline-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A technical glass design framework with SCSS source and compiled CSS - minimalist, rectangular forms with milky glass effects",
|
|
6
6
|
"main": "dist/baseline.css",
|
|
7
7
|
"style": "dist/baseline.css",
|
|
8
8
|
"sass": "src/baseline.scss",
|
|
9
|
+
"js": "dist/baseline.js",
|
|
9
10
|
"files": [
|
|
10
11
|
"dist",
|
|
11
12
|
"src",
|
|
@@ -13,11 +14,18 @@
|
|
|
13
14
|
"CHANGELOG.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"style": "./dist/baseline.css",
|
|
20
|
+
"sass": "./src/baseline.scss",
|
|
21
|
+
"js": "./dist/baseline.js",
|
|
22
|
+
"default": "./dist/baseline.css"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
16
25
|
"scripts": {
|
|
17
26
|
"build": "node build.js",
|
|
18
27
|
"watch": "node build.js --watch",
|
|
19
|
-
"docs
|
|
20
|
-
"docs:build": "storybook build",
|
|
28
|
+
"docs": "open docs/index.html",
|
|
21
29
|
"prepublishOnly": "npm run build"
|
|
22
30
|
},
|
|
23
31
|
"keywords": [
|
|
@@ -33,7 +41,8 @@
|
|
|
33
41
|
"glassmorphism",
|
|
34
42
|
"technical-design",
|
|
35
43
|
"minimalist",
|
|
36
|
-
"glass-effect"
|
|
44
|
+
"glass-effect",
|
|
45
|
+
"javascript"
|
|
37
46
|
],
|
|
38
47
|
"author": "",
|
|
39
48
|
"license": "MIT",
|
|
@@ -46,14 +55,7 @@
|
|
|
46
55
|
},
|
|
47
56
|
"homepage": "https://github.com/e7a-0-e7a/baseline#readme",
|
|
48
57
|
"devDependencies": {
|
|
49
|
-
"@storybook/addon-essentials": "^7.6.21",
|
|
50
|
-
"@storybook/addon-interactions": "^7.6.21",
|
|
51
|
-
"@storybook/addon-links": "^7.6.21",
|
|
52
|
-
"@storybook/blocks": "^7.6.21",
|
|
53
|
-
"@storybook/html": "^7.6.21",
|
|
54
|
-
"@storybook/html-webpack5": "^7.6.21",
|
|
55
|
-
"@storybook/test": "^7.6.21",
|
|
56
58
|
"sass": "^1.69.0",
|
|
57
|
-
"
|
|
59
|
+
"esbuild": "^0.19.0"
|
|
58
60
|
}
|
|
59
61
|
}
|
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
position: relative;
|
|
18
18
|
|
|
19
19
|
// Optional: Vertical accent line at edge
|
|
20
|
-
&.bl-card-accent {
|
|
21
|
-
border-left:
|
|
20
|
+
&.bl-card-accent-left {
|
|
21
|
+
border-left: 4px solid var(--color-accent);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&.bl-card-accent-right {
|
|
25
|
+
border-right: 4px solid var(--color-accent);
|
|
22
26
|
}
|
|
23
27
|
}
|
|
24
28
|
|
|
@@ -60,18 +64,10 @@
|
|
|
60
64
|
// Card Variants
|
|
61
65
|
.bl-card-primary {
|
|
62
66
|
border-color: var(--color-accent);
|
|
63
|
-
|
|
64
|
-
&.bl-card-accent {
|
|
65
|
-
border-left-color: var(--color-accent);
|
|
66
|
-
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
.bl-card-secondary {
|
|
70
70
|
border-color: var(--glass-border-heavy);
|
|
71
|
-
|
|
72
|
-
&.bl-card-accent {
|
|
73
|
-
border-left-color: var(--color-secondary);
|
|
74
|
-
}
|
|
75
71
|
}
|
|
76
72
|
|
|
77
73
|
// Card with Shadow
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
position: absolute;
|
|
27
27
|
top: 100%;
|
|
28
28
|
left: 0;
|
|
29
|
-
z-index:
|
|
29
|
+
z-index: 99999 !important; // Immer ganz oben
|
|
30
30
|
display: none;
|
|
31
31
|
min-width: 10rem;
|
|
32
32
|
padding: var(--spacing-xs) 0;
|
|
@@ -41,6 +41,9 @@
|
|
|
41
41
|
border: 1px solid var(--glass-border-medium);
|
|
42
42
|
border-radius: var(--tech-border-radius-md);
|
|
43
43
|
overflow: hidden;
|
|
44
|
+
overflow-y: auto;
|
|
45
|
+
max-height: 300px;
|
|
46
|
+
box-shadow: var(--glass-shadow-lg);
|
|
44
47
|
|
|
45
48
|
&.bl-show {
|
|
46
49
|
display: block;
|
|
@@ -73,40 +73,191 @@
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
// Select (
|
|
76
|
+
// Select (wird automatisch zu Dropdown umgewandelt)
|
|
77
77
|
.bl-select {
|
|
78
|
+
// Wird durch JavaScript in .bl-select-dropdown umgewandelt
|
|
79
|
+
// Fallback-Styling für den Fall, dass JS nicht lädt
|
|
78
80
|
display: block;
|
|
79
81
|
width: 100%;
|
|
80
82
|
padding: var(--form-input-padding-y) var(--form-input-padding-x);
|
|
81
|
-
padding-right: calc(var(--form-input-padding-x) + 1.5rem);
|
|
83
|
+
padding-right: calc(var(--form-input-padding-x) + 1.5rem);
|
|
82
84
|
font-family: var(--font-family-base);
|
|
83
85
|
font-size: var(--form-input-font-size);
|
|
84
86
|
line-height: var(--form-input-line-height);
|
|
85
87
|
color: var(--color-text);
|
|
86
|
-
background: var(--glass-bg-
|
|
88
|
+
background: var(--glass-bg-medium);
|
|
87
89
|
border: 1px solid var(--glass-border-medium);
|
|
88
|
-
border-radius: var(--tech-border-radius-
|
|
89
|
-
backdrop-filter: blur(var(--glass-blur-
|
|
90
|
-
-webkit-backdrop-filter: blur(var(--glass-blur-
|
|
90
|
+
border-radius: var(--tech-border-radius-md);
|
|
91
|
+
backdrop-filter: blur(var(--glass-blur-lg));
|
|
92
|
+
-webkit-backdrop-filter: blur(var(--glass-blur-lg));
|
|
91
93
|
transition: var(--transition-base);
|
|
92
94
|
cursor: pointer;
|
|
93
95
|
appearance: none;
|
|
96
|
+
-webkit-appearance: none;
|
|
97
|
+
-moz-appearance: none;
|
|
94
98
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath fill='%23ffffff' d='M0 2l4 4 4-4z'/%3E%3C/svg%3E");
|
|
95
99
|
background-repeat: no-repeat;
|
|
96
100
|
background-position: right var(--form-input-padding-x) center;
|
|
97
101
|
background-size: 0.75rem;
|
|
102
|
+
box-shadow: var(--glass-shadow-sm);
|
|
98
103
|
|
|
99
104
|
&:focus {
|
|
100
105
|
outline: none;
|
|
101
106
|
border-width: 2px;
|
|
102
107
|
border-color: var(--color-accent);
|
|
103
108
|
background-color: var(--glass-bg-medium);
|
|
109
|
+
box-shadow: var(--glass-shadow-md), 0 0 0 1px var(--color-accent);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
&:hover {
|
|
113
|
+
background-color: var(--glass-bg-heavy);
|
|
114
|
+
border-color: var(--glass-border-heavy);
|
|
104
115
|
}
|
|
105
116
|
|
|
106
117
|
&:disabled {
|
|
107
118
|
opacity: var(--form-input-opacity-disabled);
|
|
108
119
|
cursor: not-allowed;
|
|
109
120
|
background-color: var(--glass-bg-dark);
|
|
121
|
+
box-shadow: none;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Wenn Select in Dropdown umgewandelt wurde, verstecken
|
|
125
|
+
&.bl-select-converted {
|
|
126
|
+
display: none;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Select Dropdown (automatisch generiert aus .bl-select)
|
|
131
|
+
.bl-select-dropdown {
|
|
132
|
+
position: relative;
|
|
133
|
+
display: block;
|
|
134
|
+
width: 100%;
|
|
135
|
+
|
|
136
|
+
.bl-select-toggle {
|
|
137
|
+
display: flex;
|
|
138
|
+
align-items: center;
|
|
139
|
+
justify-content: space-between;
|
|
140
|
+
width: 100%;
|
|
141
|
+
padding: var(--form-input-padding-y) var(--form-input-padding-x);
|
|
142
|
+
font-family: var(--font-family-base);
|
|
143
|
+
font-size: var(--form-input-font-size);
|
|
144
|
+
line-height: var(--form-input-line-height);
|
|
145
|
+
color: var(--color-text);
|
|
146
|
+
background: var(--glass-bg-medium);
|
|
147
|
+
border: 1px solid var(--glass-border-medium);
|
|
148
|
+
border-radius: var(--tech-border-radius-md);
|
|
149
|
+
backdrop-filter: blur(var(--glass-blur-lg));
|
|
150
|
+
-webkit-backdrop-filter: blur(var(--glass-blur-lg));
|
|
151
|
+
transition: var(--transition-base);
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
box-shadow: var(--glass-shadow-sm);
|
|
154
|
+
text-align: left;
|
|
155
|
+
border: none; // Reset button border
|
|
156
|
+
|
|
157
|
+
&::after {
|
|
158
|
+
display: inline-block;
|
|
159
|
+
margin-left: var(--spacing-xs);
|
|
160
|
+
vertical-align: 0.255em;
|
|
161
|
+
content: "";
|
|
162
|
+
border-top: 0.3em solid var(--color-text);
|
|
163
|
+
border-right: 0.3em solid transparent;
|
|
164
|
+
border-bottom: 0;
|
|
165
|
+
border-left: 0.3em solid transparent;
|
|
166
|
+
flex-shrink: 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
&:focus {
|
|
170
|
+
outline: none;
|
|
171
|
+
border-width: 2px;
|
|
172
|
+
border-color: var(--color-accent);
|
|
173
|
+
box-shadow: var(--glass-shadow-md), 0 0 0 1px var(--color-accent);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
&:hover {
|
|
177
|
+
background-color: var(--glass-bg-heavy);
|
|
178
|
+
border-color: var(--glass-border-heavy);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
&:disabled {
|
|
182
|
+
opacity: var(--form-input-opacity-disabled);
|
|
183
|
+
cursor: not-allowed;
|
|
184
|
+
background-color: var(--glass-bg-dark);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.bl-select-menu {
|
|
189
|
+
position: absolute;
|
|
190
|
+
top: 100%;
|
|
191
|
+
left: 0;
|
|
192
|
+
z-index: 999999 !important; // Immer ganz oben
|
|
193
|
+
display: none;
|
|
194
|
+
width: 100%;
|
|
195
|
+
min-width: 100%;
|
|
196
|
+
padding: var(--spacing-xs) 0;
|
|
197
|
+
margin: var(--spacing-xs) 0 0 0;
|
|
198
|
+
font-size: var(--font-size-base);
|
|
199
|
+
color: var(--color-text);
|
|
200
|
+
text-align: left;
|
|
201
|
+
list-style: none;
|
|
202
|
+
background: var(--glass-bg-medium);
|
|
203
|
+
backdrop-filter: blur(var(--glass-blur-lg));
|
|
204
|
+
-webkit-backdrop-filter: blur(var(--glass-blur-lg));
|
|
205
|
+
border: 1px solid var(--glass-border-medium);
|
|
206
|
+
border-radius: var(--tech-border-radius-md);
|
|
207
|
+
overflow: hidden;
|
|
208
|
+
overflow-y: auto;
|
|
209
|
+
max-height: 300px;
|
|
210
|
+
box-shadow: var(--glass-shadow-lg);
|
|
211
|
+
|
|
212
|
+
&.bl-show {
|
|
213
|
+
display: block;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.bl-select-item {
|
|
218
|
+
display: block;
|
|
219
|
+
width: 100%;
|
|
220
|
+
padding: var(--spacing-sm) var(--spacing-md);
|
|
221
|
+
clear: both;
|
|
222
|
+
font-weight: var(--font-weight-normal);
|
|
223
|
+
color: var(--color-text);
|
|
224
|
+
text-align: inherit;
|
|
225
|
+
text-decoration: none;
|
|
226
|
+
white-space: nowrap;
|
|
227
|
+
background-color: transparent;
|
|
228
|
+
border: 0;
|
|
229
|
+
cursor: pointer;
|
|
230
|
+
transition: var(--transition-base);
|
|
231
|
+
|
|
232
|
+
&:hover,
|
|
233
|
+
&:focus {
|
|
234
|
+
color: var(--color-text);
|
|
235
|
+
text-decoration: none;
|
|
236
|
+
background: var(--glass-bg-heavy);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
&:active {
|
|
240
|
+
color: var(--color-text);
|
|
241
|
+
background: var(--glass-bg-heavy);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
&.bl-selected {
|
|
245
|
+
background: var(--glass-bg-heavy);
|
|
246
|
+
color: var(--color-accent);
|
|
247
|
+
|
|
248
|
+
&::before {
|
|
249
|
+
content: "✓ ";
|
|
250
|
+
margin-right: var(--spacing-xs);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
&.bl-disabled,
|
|
255
|
+
&:disabled {
|
|
256
|
+
color: var(--color-text-muted);
|
|
257
|
+
pointer-events: none;
|
|
258
|
+
background-color: transparent;
|
|
259
|
+
opacity: 0.6;
|
|
260
|
+
}
|
|
110
261
|
}
|
|
111
262
|
}
|
|
112
263
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Baseline UI JavaScript
|
|
3
|
+
// Main Entry Point
|
|
4
|
+
// ============================================================================
|
|
5
|
+
|
|
6
|
+
import { initModal, openModal, closeModal } from './components/modal.js';
|
|
7
|
+
import { initDropdown } from './components/dropdown.js';
|
|
8
|
+
import { initTooltip } from './components/tooltip.js';
|
|
9
|
+
import { initTabs } from './components/tabs.js';
|
|
10
|
+
import { initAlert, dismissAlert } from './components/alert.js';
|
|
11
|
+
|
|
12
|
+
// Export all functions for manual use
|
|
13
|
+
export {
|
|
14
|
+
initModal,
|
|
15
|
+
openModal,
|
|
16
|
+
closeModal,
|
|
17
|
+
initDropdown,
|
|
18
|
+
initTooltip,
|
|
19
|
+
initTabs,
|
|
20
|
+
initAlert,
|
|
21
|
+
dismissAlert
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Auto-initialize on DOM ready
|
|
25
|
+
function autoInit() {
|
|
26
|
+
// Initialize all modals
|
|
27
|
+
document.querySelectorAll('.bl-modal').forEach(modal => {
|
|
28
|
+
initModal(modal);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Initialize all dropdowns
|
|
32
|
+
document.querySelectorAll('.bl-dropdown').forEach(dropdown => {
|
|
33
|
+
initDropdown(dropdown);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Initialize all tooltips
|
|
37
|
+
document.querySelectorAll('.bl-tooltip').forEach(tooltip => {
|
|
38
|
+
initTooltip(tooltip);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Initialize all tabs
|
|
42
|
+
document.querySelectorAll('.bl-nav-tabs').forEach(tabs => {
|
|
43
|
+
initTabs(tabs);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Initialize all dismissible alerts
|
|
47
|
+
document.querySelectorAll('.bl-alert-dismissible').forEach(alert => {
|
|
48
|
+
initAlert(alert);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Initialize when DOM is ready
|
|
53
|
+
if (document.readyState === 'loading') {
|
|
54
|
+
document.addEventListener('DOMContentLoaded', autoInit);
|
|
55
|
+
} else {
|
|
56
|
+
// Use setTimeout to ensure DOM is fully ready
|
|
57
|
+
setTimeout(autoInit, 0);
|
|
58
|
+
}
|
|
59
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Alert Component JavaScript
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export function initAlert(alertElement) {
|
|
6
|
+
if (!alertElement) return;
|
|
7
|
+
|
|
8
|
+
const closeBtn = alertElement.querySelector('.bl-alert-close');
|
|
9
|
+
if (!closeBtn) return;
|
|
10
|
+
|
|
11
|
+
closeBtn.addEventListener('click', () => {
|
|
12
|
+
dismissAlert(alertElement);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function dismissAlert(alertElement) {
|
|
17
|
+
if (!alertElement) return;
|
|
18
|
+
|
|
19
|
+
alertElement.style.transition = 'opacity 0.3s ease-out';
|
|
20
|
+
alertElement.style.opacity = '0';
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
alertElement.remove();
|
|
23
|
+
}, 300);
|
|
24
|
+
}
|
|
25
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Dropdown Component JavaScript
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export function initDropdown(dropdownElement) {
|
|
6
|
+
if (!dropdownElement) return;
|
|
7
|
+
|
|
8
|
+
const toggle = dropdownElement.querySelector('.bl-dropdown-toggle');
|
|
9
|
+
const menu = dropdownElement.querySelector('.bl-dropdown-menu');
|
|
10
|
+
|
|
11
|
+
if (!toggle || !menu) return;
|
|
12
|
+
|
|
13
|
+
toggle.addEventListener('click', (e) => {
|
|
14
|
+
e.preventDefault();
|
|
15
|
+
e.stopPropagation();
|
|
16
|
+
|
|
17
|
+
// Close all other dropdowns
|
|
18
|
+
document.querySelectorAll('.bl-dropdown-menu.bl-show').forEach(otherMenu => {
|
|
19
|
+
if (otherMenu !== menu) {
|
|
20
|
+
otherMenu.classList.remove('bl-show');
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Toggle current dropdown
|
|
25
|
+
menu.classList.toggle('bl-show');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Close on outside click
|
|
29
|
+
const outsideClickHandler = (e) => {
|
|
30
|
+
if (!dropdownElement.contains(e.target)) {
|
|
31
|
+
menu.classList.remove('bl-show');
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
document.addEventListener('click', outsideClickHandler);
|
|
36
|
+
|
|
37
|
+
// Store handler for cleanup if needed
|
|
38
|
+
dropdownElement._outsideClickHandler = outsideClickHandler;
|
|
39
|
+
}
|
|
40
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Modal Component JavaScript
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export function initModal(modalElement) {
|
|
6
|
+
if (!modalElement) return;
|
|
7
|
+
|
|
8
|
+
const backdrop = modalElement.querySelector('.bl-modal-backdrop') || document.createElement('div');
|
|
9
|
+
if (!backdrop.classList.contains('bl-modal-backdrop')) {
|
|
10
|
+
backdrop.className = 'bl-modal-backdrop';
|
|
11
|
+
modalElement.insertBefore(backdrop, modalElement.firstChild);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Open modal buttons
|
|
15
|
+
const modalId = modalElement.id;
|
|
16
|
+
if (modalId) {
|
|
17
|
+
const openButtons = document.querySelectorAll(`[data-modal-open="${modalId}"]`);
|
|
18
|
+
openButtons.forEach(btn => {
|
|
19
|
+
btn.addEventListener('click', () => {
|
|
20
|
+
openModal(modalId);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Close modal buttons
|
|
26
|
+
const closeButtons = modalElement.querySelectorAll('.bl-modal-close, [data-modal-close]');
|
|
27
|
+
closeButtons.forEach(btn => {
|
|
28
|
+
btn.addEventListener('click', () => {
|
|
29
|
+
closeModal(modalId);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Close on backdrop click
|
|
34
|
+
backdrop.addEventListener('click', (e) => {
|
|
35
|
+
if (e.target === backdrop) {
|
|
36
|
+
closeModal(modalId);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Close on ESC key
|
|
41
|
+
const escHandler = (e) => {
|
|
42
|
+
if (e.key === 'Escape' && modalElement.style.display === 'block') {
|
|
43
|
+
closeModal(modalId);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
document.addEventListener('keydown', escHandler);
|
|
47
|
+
|
|
48
|
+
// Store handler for cleanup if needed
|
|
49
|
+
modalElement._escHandler = escHandler;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function openModal(modalId) {
|
|
53
|
+
const modal = document.getElementById(modalId);
|
|
54
|
+
if (modal) {
|
|
55
|
+
modal.style.display = 'block';
|
|
56
|
+
document.body.style.overflow = 'hidden';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function closeModal(modalId) {
|
|
61
|
+
const modal = document.getElementById(modalId);
|
|
62
|
+
if (modal) {
|
|
63
|
+
modal.style.display = 'none';
|
|
64
|
+
document.body.style.overflow = '';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tabs Component JavaScript
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export function initTabs(tabsContainer) {
|
|
6
|
+
if (!tabsContainer) return;
|
|
7
|
+
|
|
8
|
+
const tabLinks = tabsContainer.querySelectorAll('.bl-nav-link[data-tab-target]');
|
|
9
|
+
const tabGroup = tabsContainer.getAttribute('data-tab-group');
|
|
10
|
+
|
|
11
|
+
tabLinks.forEach(link => {
|
|
12
|
+
link.addEventListener('click', (e) => {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
|
|
15
|
+
// Remove active from all tabs in group
|
|
16
|
+
if (tabGroup) {
|
|
17
|
+
document.querySelectorAll(`[data-tab-group="${tabGroup}"] .bl-nav-link`).forEach(l => {
|
|
18
|
+
l.classList.remove('bl-active');
|
|
19
|
+
});
|
|
20
|
+
} else {
|
|
21
|
+
tabsContainer.querySelectorAll('.bl-nav-link').forEach(l => {
|
|
22
|
+
l.classList.remove('bl-active');
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Add active to clicked tab
|
|
27
|
+
link.classList.add('bl-active');
|
|
28
|
+
|
|
29
|
+
// Show/hide tab content
|
|
30
|
+
const targetId = link.getAttribute('data-tab-target');
|
|
31
|
+
if (targetId) {
|
|
32
|
+
// Find all tab contents - search in parent container or document
|
|
33
|
+
const container = tabsContainer.closest('.docs-example-preview') ||
|
|
34
|
+
tabsContainer.parentElement ||
|
|
35
|
+
document;
|
|
36
|
+
|
|
37
|
+
container.querySelectorAll('[data-tab-content]').forEach(content => {
|
|
38
|
+
content.style.display = 'none';
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const targetContent = document.getElementById(targetId);
|
|
42
|
+
if (targetContent) {
|
|
43
|
+
targetContent.style.display = 'block';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tooltip Component JavaScript
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export function initTooltip(tooltipElement) {
|
|
6
|
+
if (!tooltipElement) return;
|
|
7
|
+
|
|
8
|
+
const trigger = tooltipElement.querySelector('.bl-tooltip-trigger');
|
|
9
|
+
const content = tooltipElement.querySelector('.bl-tooltip-content');
|
|
10
|
+
|
|
11
|
+
if (!trigger || !content) {
|
|
12
|
+
console.warn('Baseline UI: Tooltip missing trigger or content', tooltipElement);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Skip if already initialized
|
|
17
|
+
if (trigger._tooltipInitialized) return;
|
|
18
|
+
|
|
19
|
+
// Create handlers
|
|
20
|
+
const enterHandler = () => {
|
|
21
|
+
content.classList.add('bl-show');
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const leaveHandler = () => {
|
|
25
|
+
content.classList.remove('bl-show');
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Add event listeners
|
|
29
|
+
trigger.addEventListener('mouseenter', enterHandler);
|
|
30
|
+
trigger.addEventListener('mouseleave', leaveHandler);
|
|
31
|
+
|
|
32
|
+
// Mark as initialized
|
|
33
|
+
trigger._tooltipInitialized = true;
|
|
34
|
+
trigger._tooltipEnterHandler = enterHandler;
|
|
35
|
+
trigger._tooltipLeaveHandler = leaveHandler;
|
|
36
|
+
}
|
|
37
|
+
|