@shohojdhara/atomix 0.4.4 → 0.4.6
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/dist/atomix.css +50 -11
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.js +184 -189
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +4 -4
- package/dist/core.js +194 -199
- package/dist/core.js.map +1 -1
- package/dist/forms.js +184 -189
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +189 -194
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +44 -47
- package/dist/index.esm.js +496 -613
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +528 -631
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +60 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +8 -42
- package/src/components/AtomixGlass/glass-utils.ts +27 -14
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +19 -21
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +1162 -515
- package/src/components/AtomixGlass/stories/shared-components.tsx +11 -3
- package/src/components/Breadcrumb/Breadcrumb.tsx +5 -5
- package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +2 -2
- package/src/components/Button/Button.tsx +6 -6
- package/src/components/Card/Card.tsx +3 -3
- package/src/components/Dropdown/Dropdown.tsx +5 -3
- package/src/components/Footer/Footer.tsx +124 -166
- package/src/components/Footer/FooterLink.tsx +16 -19
- package/src/components/Footer/FooterSection.tsx +40 -39
- package/src/components/Footer/FooterSocialLink.tsx +59 -58
- package/src/components/Footer/README.md +1 -1
- package/src/components/Hero/Hero.tsx +72 -142
- package/src/components/Navigation/Menu/MegaMenu.tsx +17 -12
- package/src/components/Navigation/Menu/Menu.tsx +49 -24
- package/src/components/Navigation/Nav/NavItem.tsx +5 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +13 -5
- package/src/components/Navigation/SideMenu/SideMenu.tsx +2 -2
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -4
- package/src/components/Slider/Slider.tsx +7 -4
- package/src/lib/composables/index.ts +1 -2
- package/src/lib/composables/useAtomixGlass.ts +246 -222
- package/src/lib/composables/useAtomixGlassStyles.ts +46 -23
- package/src/lib/composables/useFooter.ts +117 -20
- package/src/lib/composables/useSlider.ts +3 -1
- package/src/lib/constants/components.ts +3 -1
- package/src/lib/types/components.ts +44 -12
- package/src/styles/06-components/_components.atomix-glass.scss +72 -14
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +0 -222
- package/src/lib/composables/atomix-glass/useGlassBackgroundDetection.ts +0 -329
- package/src/lib/composables/atomix-glass/useGlassCornerRadius.ts +0 -82
- package/src/lib/composables/atomix-glass/useGlassMouseTracking.ts +0 -153
- package/src/lib/composables/atomix-glass/useGlassOverLight.ts +0 -198
- package/src/lib/composables/atomix-glass/useGlassState.ts +0 -112
- package/src/lib/composables/atomix-glass/useGlassTransforms.ts +0 -160
- package/src/lib/composables/glass-styles.ts +0 -302
- package/src/lib/composables/useGlassContainer.ts +0 -177
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ATOMIX_GLASS } from '../constants/components';
|
|
2
|
-
import { calculateDistance, calculateElementCenter, calculateMouseInfluence, validateGlassSize, clampBlur } from '../../components/AtomixGlass/glass-utils';
|
|
2
|
+
import { calculateDistance, calculateElementCenter, calculateMouseInfluence, validateGlassSize, clampBlur, smoothstep, softClamp } from '../../components/AtomixGlass/glass-utils';
|
|
3
3
|
import type { GlassSize, MousePosition, OverLightObjectConfig } from '../types/components';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -73,30 +73,53 @@ export const updateAtomixGlassStyles = (
|
|
|
73
73
|
saturationBoost: baseOverLightConfig.saturationBoost
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
76
|
+
let computedDirectionalScale = directionalScale;
|
|
77
|
+
|
|
78
|
+
// Calculate elastic translation and directional scale
|
|
79
|
+
let elasticTranslation = { x: 0, y: 0 };
|
|
80
|
+
if (!effectiveWithoutEffects && wrapperElement) {
|
|
81
|
+
const rect = wrapperElement.getBoundingClientRect();
|
|
82
|
+
const center = calculateElementCenter(rect);
|
|
83
|
+
|
|
84
|
+
// Mouse presence and edge distance logic
|
|
85
|
+
if (globalMousePosition.x && globalMousePosition.y && validateGlassSize(glassSize)) {
|
|
86
|
+
const deltaX = globalMousePosition.x - center.x;
|
|
87
|
+
const deltaY = globalMousePosition.y - center.y;
|
|
88
|
+
const edgeDistanceX = Math.max(0, Math.abs(deltaX) - glassSize.width / 2);
|
|
89
|
+
const edgeDistanceY = Math.max(0, Math.abs(deltaY) - glassSize.height / 2);
|
|
90
|
+
const edgeDistance = calculateDistance({ x: edgeDistanceX, y: edgeDistanceY }, { x: 0, y: 0 });
|
|
91
|
+
|
|
92
|
+
// Elastic translation
|
|
93
|
+
const rawT = edgeDistance > ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE ? 0 : 1 - edgeDistance / ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE;
|
|
94
|
+
const fadeInFactor = smoothstep(rawT);
|
|
95
|
+
elasticTranslation = {
|
|
96
|
+
x: deltaX * elasticity * 0.1 * fadeInFactor,
|
|
97
|
+
y: deltaY * elasticity * 0.1 * fadeInFactor,
|
|
98
|
+
};
|
|
90
99
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
// Directional scale
|
|
101
|
+
if (!isOverLight && edgeDistance <= ATOMIX_GLASS.CONSTANTS.ACTIVATION_ZONE) {
|
|
102
|
+
const centerDistance = calculateDistance(globalMousePosition, center);
|
|
103
|
+
if (centerDistance > 0) {
|
|
104
|
+
const normalizedX = deltaX / centerDistance;
|
|
105
|
+
const normalizedY = deltaY / centerDistance;
|
|
106
|
+
const stretchIntensity = Math.min(centerDistance / 300, 1) * elasticity * rawT;
|
|
107
|
+
|
|
108
|
+
const scaleX = 1 + Math.abs(normalizedX) * stretchIntensity * 0.3 - Math.abs(normalizedY) * stretchIntensity * 0.15;
|
|
109
|
+
const scaleY = 1 + Math.abs(normalizedY) * stretchIntensity * 0.3 - Math.abs(normalizedX) * stretchIntensity * 0.15;
|
|
110
|
+
|
|
111
|
+
const softScaleX = 1 - softClamp(Math.max(0, 1 - scaleX), 0.2);
|
|
112
|
+
const softScaleY = 1 - softClamp(Math.max(0, 1 - scaleY), 0.2);
|
|
113
|
+
|
|
114
|
+
computedDirectionalScale = `scaleX(${Math.max(0.85, softScaleX)}) scaleY(${Math.max(0.85, softScaleY)})`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
96
119
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
120
|
+
const transformStyle = effectiveWithoutEffects
|
|
121
|
+
? isActive && Boolean(onClick) ? 'scale(0.98)' : 'scale(1)'
|
|
122
|
+
: `translate(${elasticTranslation.x}px, ${elasticTranslation.y}px) ${isActive && Boolean(onClick) ? 'scale(0.96)' : computedDirectionalScale}`;
|
|
100
123
|
|
|
101
124
|
// Update Wrapper Styles (glassVars)
|
|
102
125
|
if (wrapperElement) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
1
2
|
import { FooterLayout, ThemeColor, Size, SocialLink } from '../types/components';
|
|
2
3
|
import { FOOTER } from '../constants/components';
|
|
3
4
|
|
|
@@ -8,61 +9,149 @@ export interface UseFooterOptions {
|
|
|
8
9
|
sticky?: boolean;
|
|
9
10
|
showNewsletter?: boolean;
|
|
10
11
|
showBackToTop?: boolean;
|
|
12
|
+
showDivider?: boolean;
|
|
11
13
|
socialLinks?: SocialLink[];
|
|
12
14
|
onNewsletterSubmit?: (email: string) => void | Promise<void>;
|
|
13
15
|
onBackToTop?: () => void;
|
|
16
|
+
glass?: boolean;
|
|
14
17
|
className?: string;
|
|
15
18
|
}
|
|
16
19
|
|
|
20
|
+
/** Raw column size map per layout */
|
|
21
|
+
type ColumnSizeMap = {
|
|
22
|
+
brand: number | 'auto';
|
|
23
|
+
content: number | 'auto';
|
|
24
|
+
newsletter: number | 'auto';
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Resolves grid column size map for a given layout.
|
|
29
|
+
*/
|
|
30
|
+
function resolveColumnSizes(layout: FooterLayout, showNewsletter: boolean): ColumnSizeMap {
|
|
31
|
+
switch (layout) {
|
|
32
|
+
case 'columns':
|
|
33
|
+
return {
|
|
34
|
+
brand: 4,
|
|
35
|
+
content: showNewsletter ? 4 : 8,
|
|
36
|
+
newsletter: showNewsletter ? 4 : 0,
|
|
37
|
+
};
|
|
38
|
+
case 'centered':
|
|
39
|
+
case 'minimal':
|
|
40
|
+
case 'stacked':
|
|
41
|
+
return {
|
|
42
|
+
brand: 12,
|
|
43
|
+
content: 12,
|
|
44
|
+
newsletter: showNewsletter ? 12 : 0,
|
|
45
|
+
};
|
|
46
|
+
case 'flexible':
|
|
47
|
+
return { brand: 'auto', content: 'auto', newsletter: 'auto' };
|
|
48
|
+
case 'sidebar':
|
|
49
|
+
return {
|
|
50
|
+
brand: 3,
|
|
51
|
+
content: 9,
|
|
52
|
+
newsletter: showNewsletter ? 9 : 0,
|
|
53
|
+
};
|
|
54
|
+
case 'wide':
|
|
55
|
+
return {
|
|
56
|
+
brand: 3,
|
|
57
|
+
content: 6,
|
|
58
|
+
newsletter: showNewsletter ? 3 : 0,
|
|
59
|
+
};
|
|
60
|
+
default:
|
|
61
|
+
return {
|
|
62
|
+
brand: 4,
|
|
63
|
+
content: showNewsletter ? 4 : 8,
|
|
64
|
+
newsletter: showNewsletter ? 4 : 0,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Computes responsive GridCol props for a given column type.
|
|
71
|
+
*/
|
|
72
|
+
function resolveResponsiveColProps(
|
|
73
|
+
columnType: 'brand' | 'content' | 'newsletter',
|
|
74
|
+
layout: FooterLayout,
|
|
75
|
+
columnSizes: ColumnSizeMap
|
|
76
|
+
): Record<string, number | boolean> {
|
|
77
|
+
if (layout === 'flexible' && columnSizes[columnType] === 'auto') {
|
|
78
|
+
return { xs: 12, sm: true, md: true };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const isMultiColumn = layout === 'columns' || layout === 'sidebar' || layout === 'wide';
|
|
82
|
+
const baseMd = isMultiColumn ? columnSizes[columnType] : 12;
|
|
83
|
+
|
|
84
|
+
return { xs: 12, md: baseMd as number };
|
|
85
|
+
}
|
|
86
|
+
|
|
17
87
|
export function useFooter(options: UseFooterOptions = {}) {
|
|
18
88
|
const {
|
|
19
|
-
layout = FOOTER.DEFAULTS.LAYOUT,
|
|
89
|
+
layout = FOOTER.DEFAULTS.LAYOUT as FooterLayout,
|
|
20
90
|
variant = FOOTER.DEFAULTS.VARIANT,
|
|
21
|
-
size = FOOTER.DEFAULTS.SIZE,
|
|
91
|
+
size = FOOTER.DEFAULTS.SIZE as Size,
|
|
22
92
|
sticky = FOOTER.DEFAULTS.STICKY,
|
|
23
93
|
showNewsletter = FOOTER.DEFAULTS.SHOW_NEWSLETTER,
|
|
24
94
|
showBackToTop = FOOTER.DEFAULTS.SHOW_BACK_TO_TOP,
|
|
95
|
+
showDivider = FOOTER.DEFAULTS.SHOW_DIVIDER,
|
|
25
96
|
socialLinks = [],
|
|
26
97
|
onNewsletterSubmit,
|
|
27
98
|
onBackToTop,
|
|
99
|
+
glass = false,
|
|
28
100
|
className = '',
|
|
29
101
|
} = options;
|
|
30
102
|
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
103
|
+
// ---------- CSS class strings ----------
|
|
104
|
+
|
|
105
|
+
const footerClass = useMemo(() => {
|
|
106
|
+
const layoutKey = layout.toUpperCase() as keyof typeof FOOTER.CLASSES;
|
|
107
|
+
const sizeKey = size.toUpperCase() as keyof typeof FOOTER.CLASSES;
|
|
108
|
+
|
|
109
|
+
return [
|
|
34
110
|
FOOTER.CLASSES.BASE,
|
|
35
|
-
FOOTER.CLASSES[
|
|
111
|
+
FOOTER.CLASSES[layoutKey] || FOOTER.CLASSES.COLUMNS,
|
|
36
112
|
`c-footer--${variant}`,
|
|
37
|
-
FOOTER.CLASSES[
|
|
113
|
+
FOOTER.CLASSES[sizeKey] || FOOTER.CLASSES.MD,
|
|
38
114
|
sticky && FOOTER.CLASSES.STICKY,
|
|
39
115
|
showNewsletter && 'c-footer--with-newsletter',
|
|
116
|
+
glass && 'c-footer--glass',
|
|
40
117
|
className,
|
|
41
|
-
]
|
|
42
|
-
|
|
43
|
-
|
|
118
|
+
]
|
|
119
|
+
.filter(Boolean)
|
|
120
|
+
.join(' ');
|
|
121
|
+
}, [layout, variant, size, sticky, showNewsletter, glass, className]);
|
|
44
122
|
|
|
45
123
|
const containerClass = FOOTER.CLASSES.CONTAINER;
|
|
46
124
|
const brandClass = FOOTER.CLASSES.BRAND;
|
|
47
|
-
|
|
48
|
-
|
|
125
|
+
|
|
126
|
+
const sectionsClass = useMemo(() => {
|
|
127
|
+
return [
|
|
49
128
|
FOOTER.CLASSES.SECTIONS,
|
|
50
129
|
layout === 'columns' && 'c-footer__sections--columns',
|
|
51
130
|
layout === 'centered' && 'c-footer__sections--centered',
|
|
52
131
|
layout === 'stacked' && 'c-footer__sections--stacked',
|
|
53
|
-
]
|
|
54
|
-
|
|
55
|
-
|
|
132
|
+
]
|
|
133
|
+
.filter(Boolean)
|
|
134
|
+
.join(' ');
|
|
135
|
+
}, [layout]);
|
|
136
|
+
|
|
56
137
|
const bottomClass = FOOTER.CLASSES.BOTTOM;
|
|
57
138
|
|
|
58
|
-
//
|
|
139
|
+
// ---------- Grid helpers ----------
|
|
140
|
+
|
|
141
|
+
const columnSizes = useMemo(
|
|
142
|
+
() => resolveColumnSizes(layout, showNewsletter),
|
|
143
|
+
[layout, showNewsletter]
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const getResponsiveColumnProps = (columnType: 'brand' | 'content' | 'newsletter') =>
|
|
147
|
+
resolveResponsiveColProps(columnType, layout, columnSizes);
|
|
148
|
+
|
|
149
|
+
// ---------- Handlers ----------
|
|
150
|
+
|
|
59
151
|
const handleNewsletterSubmit = (email: string) => {
|
|
60
|
-
|
|
61
|
-
onNewsletterSubmit(email);
|
|
62
|
-
}
|
|
152
|
+
onNewsletterSubmit?.(email);
|
|
63
153
|
};
|
|
64
154
|
|
|
65
|
-
// Handle back to top
|
|
66
155
|
const handleBackToTop = () => {
|
|
67
156
|
if (onBackToTop) {
|
|
68
157
|
onBackToTop();
|
|
@@ -72,14 +161,22 @@ export function useFooter(options: UseFooterOptions = {}) {
|
|
|
72
161
|
};
|
|
73
162
|
|
|
74
163
|
return {
|
|
164
|
+
// Classes
|
|
75
165
|
footerClass,
|
|
76
166
|
containerClass,
|
|
77
167
|
brandClass,
|
|
78
168
|
sectionsClass,
|
|
79
169
|
bottomClass,
|
|
170
|
+
// Grid helpers
|
|
171
|
+
columnSizes,
|
|
172
|
+
getResponsiveColumnProps,
|
|
173
|
+
// Handlers
|
|
80
174
|
handleNewsletterSubmit,
|
|
81
175
|
handleBackToTop,
|
|
176
|
+
// Pass-through state
|
|
82
177
|
socialLinks,
|
|
83
178
|
showNewsletter,
|
|
179
|
+
showBackToTop,
|
|
180
|
+
showDivider,
|
|
84
181
|
};
|
|
85
182
|
}
|
|
@@ -26,7 +26,7 @@ export interface UseSliderReturn extends SliderState {
|
|
|
26
26
|
|
|
27
27
|
export function useSlider(options: UseSliderOptions): UseSliderReturn {
|
|
28
28
|
const {
|
|
29
|
-
slides,
|
|
29
|
+
slides: rawSlides,
|
|
30
30
|
slidesToShow = 1,
|
|
31
31
|
spaceBetween = 0,
|
|
32
32
|
loop = false,
|
|
@@ -39,6 +39,8 @@ export function useSlider(options: UseSliderOptions): UseSliderReturn {
|
|
|
39
39
|
onSlideChange,
|
|
40
40
|
} = options;
|
|
41
41
|
|
|
42
|
+
const slides = Array.isArray(rawSlides) ? rawSlides : [];
|
|
43
|
+
|
|
42
44
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
43
45
|
const wrapperRef = useRef<HTMLDivElement | null>(null);
|
|
44
46
|
const repositioningRef = useRef(false);
|
|
@@ -1663,7 +1663,9 @@ export const ATOMIX_GLASS = {
|
|
|
1663
1663
|
ENABLE_OVER_LIGHT_LAYERS: true,
|
|
1664
1664
|
},
|
|
1665
1665
|
CONSTANTS: {
|
|
1666
|
-
ACTIVATION_ZONE:
|
|
1666
|
+
ACTIVATION_ZONE: 350,
|
|
1667
|
+
LERP_FACTOR: 0.08,
|
|
1668
|
+
SMOOTHSTEP_POWER: 2.5,
|
|
1667
1669
|
MIN_BLUR: 0.1,
|
|
1668
1670
|
MOUSE_INFLUENCE_DIVISOR: 100,
|
|
1669
1671
|
EDGE_FADE_PIXELS: 2,
|
|
@@ -1344,6 +1344,11 @@ export interface NavItemProps extends BaseComponentProps {
|
|
|
1344
1344
|
*/
|
|
1345
1345
|
href?: string;
|
|
1346
1346
|
|
|
1347
|
+
/**
|
|
1348
|
+
* Link target attribute (used with href)
|
|
1349
|
+
*/
|
|
1350
|
+
target?: '_blank' | '_self' | '_parent' | '_top';
|
|
1351
|
+
|
|
1347
1352
|
/**
|
|
1348
1353
|
* Optional click handler
|
|
1349
1354
|
*/
|
|
@@ -1357,7 +1362,7 @@ export interface NavItemProps extends BaseComponentProps {
|
|
|
1357
1362
|
/**
|
|
1358
1363
|
* Optional custom link component
|
|
1359
1364
|
*/
|
|
1360
|
-
|
|
1365
|
+
linkComponent?: React.ElementType;
|
|
1361
1366
|
}
|
|
1362
1367
|
|
|
1363
1368
|
/**
|
|
@@ -1409,6 +1414,16 @@ export interface MenuItemProps extends BaseComponentProps {
|
|
|
1409
1414
|
*/
|
|
1410
1415
|
href?: string;
|
|
1411
1416
|
|
|
1417
|
+
/**
|
|
1418
|
+
* Link target attribute (used with href)
|
|
1419
|
+
*/
|
|
1420
|
+
target?: '_blank' | '_self' | '_parent' | '_top';
|
|
1421
|
+
|
|
1422
|
+
/**
|
|
1423
|
+
* Optional custom link component
|
|
1424
|
+
*/
|
|
1425
|
+
linkComponent?: React.ElementType;
|
|
1426
|
+
|
|
1412
1427
|
/**
|
|
1413
1428
|
* Item icon
|
|
1414
1429
|
*/
|
|
@@ -1469,6 +1484,18 @@ export interface MegaMenuLinkProps extends BaseComponentProps {
|
|
|
1469
1484
|
*/
|
|
1470
1485
|
href: string;
|
|
1471
1486
|
|
|
1487
|
+
/**
|
|
1488
|
+
* Link target attribute (used with href)
|
|
1489
|
+
*/
|
|
1490
|
+
target?: '_blank' | '_self' | '_parent' | '_top';
|
|
1491
|
+
|
|
1492
|
+
/**
|
|
1493
|
+
* Optional custom link component
|
|
1494
|
+
*/
|
|
1495
|
+
linkComponent?: React.ElementType;
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
|
|
1472
1499
|
/**
|
|
1473
1500
|
* Link content
|
|
1474
1501
|
*/
|
|
@@ -1544,14 +1571,14 @@ export interface SideMenuProps extends BaseComponentProps {
|
|
|
1544
1571
|
* ```tsx
|
|
1545
1572
|
* // Next.js
|
|
1546
1573
|
* import Link from 'next/link';
|
|
1547
|
-
* <SideMenu
|
|
1574
|
+
* <SideMenu linkComponent={Link} />
|
|
1548
1575
|
*
|
|
1549
1576
|
* // React Router
|
|
1550
1577
|
* import { Link } from 'react-router-dom';
|
|
1551
|
-
* <SideMenu
|
|
1578
|
+
* <SideMenu linkComponent={Link} />
|
|
1552
1579
|
* ```
|
|
1553
1580
|
*/
|
|
1554
|
-
|
|
1581
|
+
linkComponent?: React.ElementType;
|
|
1555
1582
|
|
|
1556
1583
|
/**
|
|
1557
1584
|
* Menu items
|
|
@@ -1623,7 +1650,7 @@ export interface SideMenuItemProps extends BaseComponentProps {
|
|
|
1623
1650
|
/**
|
|
1624
1651
|
* Link target attribute
|
|
1625
1652
|
*/
|
|
1626
|
-
target?:
|
|
1653
|
+
target?: '_blank' | '_self' | '_parent' | '_top';
|
|
1627
1654
|
|
|
1628
1655
|
/**
|
|
1629
1656
|
* Link rel attribute
|
|
@@ -1632,20 +1659,20 @@ export interface SideMenuItemProps extends BaseComponentProps {
|
|
|
1632
1659
|
|
|
1633
1660
|
/**
|
|
1634
1661
|
* Optional custom link component (e.g., Next.js Link, React Router Link)
|
|
1635
|
-
* If not provided, will use
|
|
1662
|
+
* If not provided, will use linkComponent from parent SideMenu context
|
|
1636
1663
|
*
|
|
1637
1664
|
* @example
|
|
1638
1665
|
* ```tsx
|
|
1639
1666
|
* // Next.js
|
|
1640
1667
|
* import Link from 'next/link';
|
|
1641
|
-
* <SideMenuItem href="/about"
|
|
1668
|
+
* <SideMenuItem href="/about" linkComponent={Link}>About</SideMenuItem>
|
|
1642
1669
|
*
|
|
1643
1670
|
* // React Router
|
|
1644
1671
|
* import { Link } from 'react-router-dom';
|
|
1645
|
-
* <SideMenuItem href="/about"
|
|
1672
|
+
* <SideMenuItem href="/about" linkComponent={Link}>About</SideMenuItem>
|
|
1646
1673
|
* ```
|
|
1647
1674
|
*/
|
|
1648
|
-
|
|
1675
|
+
linkComponent?: React.ElementType;
|
|
1649
1676
|
}
|
|
1650
1677
|
|
|
1651
1678
|
/**
|
|
@@ -3460,6 +3487,11 @@ export interface DropdownItemProps extends BaseComponentProps {
|
|
|
3460
3487
|
*/
|
|
3461
3488
|
href?: string;
|
|
3462
3489
|
|
|
3490
|
+
/**
|
|
3491
|
+
* Link target attribute (used with href)
|
|
3492
|
+
*/
|
|
3493
|
+
target?: '_blank' | '_self' | '_parent' | '_top';
|
|
3494
|
+
|
|
3463
3495
|
/**
|
|
3464
3496
|
* Whether item is active
|
|
3465
3497
|
*/
|
|
@@ -3483,7 +3515,7 @@ export interface DropdownItemProps extends BaseComponentProps {
|
|
|
3483
3515
|
/**
|
|
3484
3516
|
* Optional custom link component
|
|
3485
3517
|
*/
|
|
3486
|
-
|
|
3518
|
+
linkComponent?: React.ElementType;
|
|
3487
3519
|
}
|
|
3488
3520
|
|
|
3489
3521
|
/**
|
|
@@ -4044,7 +4076,7 @@ export interface CardProps extends BaseComponentProps {
|
|
|
4044
4076
|
/**
|
|
4045
4077
|
* Optional custom link component (e.g., Next.js Link, React Router Link)
|
|
4046
4078
|
*/
|
|
4047
|
-
|
|
4079
|
+
linkComponent?: React.ElementType;
|
|
4048
4080
|
|
|
4049
4081
|
/**
|
|
4050
4082
|
* Optional click handler
|
|
@@ -6549,7 +6581,7 @@ export interface FooterLinkProps extends BaseComponentProps {
|
|
|
6549
6581
|
/**
|
|
6550
6582
|
* Custom link component (e.g., React Router Link)
|
|
6551
6583
|
*/
|
|
6552
|
-
|
|
6584
|
+
linkComponent?: React.ElementType;
|
|
6553
6585
|
}
|
|
6554
6586
|
|
|
6555
6587
|
/**
|
|
@@ -9,16 +9,53 @@
|
|
|
9
9
|
// CSS custom property defaults
|
|
10
10
|
--atomix-glass-radius: var(--atomix-radius-md, 16px);
|
|
11
11
|
--atomix-glass-transform: none;
|
|
12
|
-
--atomix-glass-transition: transform var(--atomix-transition-duration, 0.
|
|
12
|
+
--atomix-glass-transition: transform var(--atomix-transition-duration, 0.45s)
|
|
13
|
+
cubic-bezier(0.22, 1, 0.36, 1);
|
|
13
14
|
--atomix-glass-position: absolute;
|
|
14
15
|
--atomix-glass-container-width: 100%;
|
|
15
16
|
--atomix-glass-container-height: 100%;
|
|
16
17
|
--atomix-glass-border-width: var(--atomix-spacing-0-5, 0.09375rem);
|
|
17
18
|
|
|
19
|
+
// =========================================================================
|
|
20
|
+
// Z-INDEX STACKING ORDER (local scale, scoped to this component)
|
|
21
|
+
// =========================================================================
|
|
22
|
+
// 0: background layers
|
|
23
|
+
// 1: container (wraps filter + content)
|
|
24
|
+
// 2: base / overlay effect layers
|
|
25
|
+
// 3: hover effect layers
|
|
26
|
+
// 4: overlay-highlight
|
|
27
|
+
// 5: border-1
|
|
28
|
+
// 6: border-2
|
|
29
|
+
// =========================================================================
|
|
30
|
+
// Internal layers within the container:
|
|
31
|
+
// filter = base + 1
|
|
32
|
+
// content = base + 7
|
|
33
|
+
// =========================================================================
|
|
34
|
+
--atomix-glass-base-z-index: 0;
|
|
35
|
+
|
|
36
|
+
--_glass-z-background: calc(var(--atomix-glass-base-z-index) + 0);
|
|
37
|
+
--_glass-z-container: calc(var(--atomix-glass-base-z-index) + 1);
|
|
38
|
+
--_glass-z-filter: calc(var(--atomix-glass-base-z-index) + 1);
|
|
39
|
+
--_glass-z-effect: calc(var(--atomix-glass-base-z-index) + 2);
|
|
40
|
+
--_glass-z-hover: calc(var(--atomix-glass-base-z-index) + 3);
|
|
41
|
+
--_glass-z-overlay-highlight: calc(var(--atomix-glass-base-z-index) + 4);
|
|
42
|
+
--_glass-z-border-1: calc(var(--atomix-glass-base-z-index) + 5);
|
|
43
|
+
--_glass-z-border-2: calc(var(--atomix-glass-base-z-index) + 6);
|
|
44
|
+
--_glass-z-content: calc(var(--atomix-glass-base-z-index) + 7);
|
|
45
|
+
|
|
18
46
|
// Base layer styles for all effect layers (hover, border, overlay)
|
|
19
47
|
&__hover-1,
|
|
20
48
|
&__hover-2,
|
|
21
|
-
&__hover-3
|
|
49
|
+
&__hover-3 {
|
|
50
|
+
position: absolute;
|
|
51
|
+
inset: 0;
|
|
52
|
+
pointer-events: none;
|
|
53
|
+
border-radius: var(--atomix-glass-radius);
|
|
54
|
+
transform: var(--atomix-glass-transform);
|
|
55
|
+
transition: var(--atomix-glass-transition);
|
|
56
|
+
z-index: var(--_glass-z-hover);
|
|
57
|
+
}
|
|
58
|
+
|
|
22
59
|
&__base,
|
|
23
60
|
&__overlay {
|
|
24
61
|
position: absolute;
|
|
@@ -27,6 +64,7 @@
|
|
|
27
64
|
border-radius: var(--atomix-glass-radius);
|
|
28
65
|
transform: var(--atomix-glass-transform);
|
|
29
66
|
transition: var(--atomix-glass-transition);
|
|
67
|
+
z-index: var(--_glass-z-effect);
|
|
30
68
|
}
|
|
31
69
|
|
|
32
70
|
// Interactive hover effects
|
|
@@ -40,19 +78,25 @@
|
|
|
40
78
|
}
|
|
41
79
|
|
|
42
80
|
&__hover-1 {
|
|
43
|
-
transition:
|
|
81
|
+
transition:
|
|
82
|
+
opacity 0.2s cubic-bezier(0.22, 1, 0.36, 1),
|
|
83
|
+
background 0.35s cubic-bezier(0.22, 1, 0.36, 1);
|
|
44
84
|
opacity: var(--atomix-glass-hover-1-opacity, 0);
|
|
45
85
|
background: var(--atomix-glass-hover-1-gradient, none);
|
|
46
86
|
}
|
|
47
87
|
|
|
48
88
|
&__hover-2 {
|
|
49
|
-
transition:
|
|
89
|
+
transition:
|
|
90
|
+
opacity 0.35s cubic-bezier(0.22, 1, 0.36, 1),
|
|
91
|
+
background 0.45s cubic-bezier(0.22, 1, 0.36, 1);
|
|
50
92
|
opacity: var(--atomix-glass-hover-2-opacity, 0);
|
|
51
93
|
background: var(--atomix-glass-hover-2-gradient, none);
|
|
52
94
|
}
|
|
53
95
|
|
|
54
96
|
&__hover-3 {
|
|
55
|
-
transition:
|
|
97
|
+
transition:
|
|
98
|
+
opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
|
|
99
|
+
background 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
|
56
100
|
opacity: var(--atomix-glass-hover-3-opacity, 0);
|
|
57
101
|
background: var(--atomix-glass-hover-3-gradient, none);
|
|
58
102
|
}
|
|
@@ -80,9 +124,9 @@
|
|
|
80
124
|
transform: var(--atomix-glass-transform);
|
|
81
125
|
transition: var(--atomix-glass-transition);
|
|
82
126
|
mix-blend-mode: screen;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
127
|
+
z-index: var(--_glass-z-overlay-highlight);
|
|
128
|
+
opacity: var(--atomix-glass-overlay-highlight-opacity, 0);
|
|
129
|
+
background: var(--atomix-glass-overlay-highlight-bg, none);
|
|
86
130
|
}
|
|
87
131
|
|
|
88
132
|
// Border effect layers - matching old version exactly
|
|
@@ -114,13 +158,12 @@
|
|
|
114
158
|
border-radius: var(--atomix-glass-radius);
|
|
115
159
|
transform: var(--atomix-glass-transform);
|
|
116
160
|
transition: var(--atomix-glass-transition);
|
|
117
|
-
z-index: var(--atomix-z-index-5);
|
|
118
161
|
}
|
|
119
162
|
|
|
120
163
|
&__border-1 {
|
|
121
164
|
opacity: var(--atomix-opacity-20, 0.2);
|
|
122
165
|
mix-blend-mode: screen;
|
|
123
|
-
z-index: var(--
|
|
166
|
+
z-index: var(--_glass-z-border-1);
|
|
124
167
|
background: var(--atomix-glass-border-gradient-1, none);
|
|
125
168
|
box-shadow: var(
|
|
126
169
|
--atomix-glass-border-shadow,
|
|
@@ -132,7 +175,7 @@
|
|
|
132
175
|
|
|
133
176
|
&__border-2 {
|
|
134
177
|
mix-blend-mode: overlay;
|
|
135
|
-
z-index: var(--
|
|
178
|
+
z-index: var(--_glass-z-border-2);
|
|
136
179
|
background: var(--atomix-glass-border-gradient-2, none);
|
|
137
180
|
box-shadow: var(
|
|
138
181
|
--atomix-glass-border-shadow,
|
|
@@ -149,6 +192,7 @@
|
|
|
149
192
|
position: relative;
|
|
150
193
|
border-radius: var(--atomix-glass-radius);
|
|
151
194
|
transition: var(--atomix-glass-transition);
|
|
195
|
+
z-index: var(--_glass-z-container);
|
|
152
196
|
}
|
|
153
197
|
|
|
154
198
|
&__inner {
|
|
@@ -156,6 +200,8 @@
|
|
|
156
200
|
height: var(--atomix-glass-container-height);
|
|
157
201
|
position: relative;
|
|
158
202
|
border-radius: var(--atomix-glass-radius);
|
|
203
|
+
padding: var(--atomix-glass-container-padding);
|
|
204
|
+
box-shadow: var(--atomix-glass-container-box-shadow);
|
|
159
205
|
}
|
|
160
206
|
|
|
161
207
|
&__filter {
|
|
@@ -165,6 +211,7 @@
|
|
|
165
211
|
width: 100%;
|
|
166
212
|
height: 100%;
|
|
167
213
|
pointer-events: none;
|
|
214
|
+
z-index: var(--_glass-z-filter);
|
|
168
215
|
|
|
169
216
|
svg {
|
|
170
217
|
border-radius: var(--atomix-glass-radius);
|
|
@@ -175,13 +222,18 @@
|
|
|
175
222
|
position: absolute;
|
|
176
223
|
inset: 0;
|
|
177
224
|
pointer-events: none;
|
|
178
|
-
border-radius: var(--atomix-glass-radius);
|
|
225
|
+
border-radius: var(--atomix-glass-container-radius);
|
|
226
|
+
backdrop-filter: var(--atomix-glass-container-backdrop);
|
|
179
227
|
}
|
|
180
228
|
|
|
181
229
|
&__filter-shadow {
|
|
182
230
|
position: absolute;
|
|
183
231
|
inset: var(--atomix-glass-border-width);
|
|
184
232
|
pointer-events: none;
|
|
233
|
+
border-radius: var(--atomix-glass-container-radius);
|
|
234
|
+
box-shadow: var(--atomix-glass-container-shadow);
|
|
235
|
+
opacity: var(--atomix-glass-container-shadow-opacity);
|
|
236
|
+
background: var(--atomix-glass-container-bg);
|
|
185
237
|
}
|
|
186
238
|
|
|
187
239
|
&__content {
|
|
@@ -189,15 +241,22 @@
|
|
|
189
241
|
width: var(--atomix-glass-container-width);
|
|
190
242
|
height: var(--atomix-glass-container-height);
|
|
191
243
|
border-radius: var(--atomix-glass-radius);
|
|
244
|
+
z-index: var(--_glass-z-content);
|
|
245
|
+
text-shadow: var(--atomix-glass-container-text-shadow);
|
|
192
246
|
}
|
|
193
247
|
|
|
194
248
|
// Background layers for over-light mode
|
|
195
249
|
&__background-layer {
|
|
196
|
-
position:
|
|
250
|
+
position: var(--atomix-glass-position);
|
|
251
|
+
top: var(--atomix-glass-top);
|
|
252
|
+
left: var(--atomix-glass-left);
|
|
253
|
+
width: var(--atomix-glass-width);
|
|
254
|
+
height: var(--atomix-glass-height);
|
|
197
255
|
pointer-events: none;
|
|
198
256
|
border-radius: var(--atomix-glass-radius);
|
|
199
257
|
transform: var(--atomix-glass-transform);
|
|
200
258
|
transition: var(--atomix-glass-transition);
|
|
259
|
+
z-index: var(--_glass-z-background);
|
|
201
260
|
|
|
202
261
|
&--dark {
|
|
203
262
|
background-color: var(--atomix-gray-9, #1f2937);
|
|
@@ -210,7 +269,6 @@
|
|
|
210
269
|
|
|
211
270
|
&--dark#{&}--over-light {
|
|
212
271
|
opacity: var(--atomix-opacity-50, 0.5);
|
|
213
|
-
z-index: -1;
|
|
214
272
|
}
|
|
215
273
|
|
|
216
274
|
&--black#{&}--over-light {
|