-
-
+
@for (heroType of heroTypes; track heroType.type) {
- @if (heroType.icons.length) {
-
diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.scss b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.scss
index a728bf25ec..6f7881799f 100644
--- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.scss
+++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.scss
@@ -29,7 +29,8 @@
border-radius: 8px;
overflow: hidden;
- // Dot grid pattern — covers top 800px, fades out via gradient mask
+ // Dot grid pattern — covers top 800px, fades out via gradient mask.
+ // Layered ABOVE the colored blobs so the dots overlay the glow.
&::before {
content: '';
position: absolute;
@@ -42,12 +43,12 @@
mask-image: linear-gradient(to bottom, black 0%, transparent 100%);
-webkit-mask-image: linear-gradient(to bottom, black 0%, transparent 100%);
pointer-events: none;
- z-index: 0;
+ z-index: 1;
}
- > *:not(.tb-iot-hub-installed-btn) {
+ > *:not(.tb-iot-hub-installed-btn):not(.tb-iot-hub-blob) {
position: relative;
- z-index: 1;
+ z-index: 2;
}
}
@@ -56,7 +57,7 @@
position: absolute;
top: 24px;
right: 24px;
- z-index: 2;
+ z-index: 3;
background: white;
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.08), 0 4px 8px 0 rgba(0, 0, 0, 0.08);
@@ -73,84 +74,80 @@
overflow: hidden;
}
-// Animated background gradient
-.tb-iot-hub-hero-gradient {
+// Soft colored glow blobs — direct CSS port of the design's two
+// 568×568 ellipses (Ellipse 399 right, Ellipse 400 left) with layer
+// opacity 0.16. Children of the page container so the halo spreads
+// across the whole page background, not just the hero. Fill comes
+// from the active hero type via `currentColor` (driven by
+// `[style.color]`).
+//
+// The design's "Layer Blur 240" is a Figma renderer parameter — when
+// translated to CSS `filter: blur(<σ>)` the visual match is around
+// σ=120 (Figma's radius is roughly twice the Gaussian σ used by CSS).
+// At σ=240 the kernel reaches well outside the 568px ellipse and peak
+// intensity collapses to ~58 % before opacity is applied, which
+// produced an almost invisible wash. σ=120 keeps the centre near
+// full strength while still spreading the halo across the page.
+.tb-iot-hub-blob {
position: absolute;
- inset: 0;
- transition: background 0.6s ease;
+ width: 568px;
+ height: 568px;
+ border-radius: 50%;
+ background: currentColor;
+ opacity: 0.16;
+ filter: blur(120px);
pointer-events: none;
+ z-index: 0;
+ transition: color 0.6s ease;
+ will-change: filter;
+}
+
+// Ellipse 400 — top-left corner at (-221, 56) inside the page-container.
+.tb-iot-hub-blob-left {
+ top: 56px;
+ left: -221px;
}
-// Floating icons container per type
+// Ellipse 399 — top-left corner at (1266, 259) inside a 1638-wide
+// page-container. Anchored to the right edge so it stays in place on
+// any viewport width: 1638 - (1266 + 568) = -196.
+.tb-iot-hub-blob-right {
+ top: 259px;
+ right: -196px;
+}
+
+// Floating icons cluster per type — one composite SVG with all icons baked in.
+// Active variant fades in expanding outward from the hero center; inactive
+// variants fade out collapsing back toward the center. This is achieved by
+// uniformly scaling the wrapper around its centre — peripheral icons travel
+// further than central ones, giving the "burst from / collapse to centre"
+// motion shown in the design prototype.
.tb-iot-hub-hero-icons {
position: absolute;
inset: 0;
pointer-events: none;
+ opacity: 0;
+ transform: scale(0.8);
+ transform-origin: 50% 50%;
+ transition: opacity 0.4s ease-out, transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
- // Icons start near center (translated toward center, scaled down, invisible)
- .tb-iot-hub-hero-float-icon {
- opacity: 0;
- transform: translate(var(--start-x), var(--start-y)) scale(0.9);
- transition: opacity 0.5s ease, transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
- }
-
- // Active: icons move outward to final position, scale to 1, fully visible
- &.active .tb-iot-hub-hero-float-icon {
+ &.active {
opacity: 1;
- transform: translate(0, 0) scale(1);
+ transform: scale(1);
}
}
-// Individual floating icon — SVG has rotation/bg/shadow baked in, CSS handles position + animation
-// Base: ≥1600px — 78px top icons (top: 40px), 87px bottom icons (top: 216px, bottom edge: 303px)
-.tb-iot-hub-hero-float-icon {
+// Cluster SVG — sits above the title, centered, scales with viewport.
+// Aspect ratio is preserved by the SVG's intrinsic dimensions.
+.tb-iot-hub-hero-cluster {
position: absolute;
- width: 78px;
- height: 78px;
-
- img {
- width: 100%;
- height: 100%;
- display: block;
- }
-
- // Top-left
- &.icon-pos-1 {
- top: 40px;
- left: calc(50% - 404px);
- --start-x: 40px;
- --start-y: 12px;
- }
-
- // Top-right — mirrors icon-pos-1
- &.icon-pos-2 {
- top: 40px;
- left: auto;
- right: calc(50% - 404px);
- --start-x: -40px;
- --start-y: 12px;
- }
-
- // Bottom-left — 87px bounding box
- &.icon-pos-3 {
- top: 216px;
- left: calc(50% - 487px);
- width: 87px;
- height: 87px;
- --start-x: 50px;
- --start-y: -8px;
- }
-
- // Bottom-right — 87px bounding box, mirrors icon-pos-3
- &.icon-pos-4 {
- top: 216px;
- left: auto;
- right: calc(50% - 487px);
- width: 87px;
- height: 87px;
- --start-x: -45px;
- --start-y: -4px;
- }
+ top: 40px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: min(890px, calc(100% - 80px));
+ height: auto;
+ display: block;
+ pointer-events: none;
}
.tb-iot-hub-hero-content {
@@ -673,60 +670,18 @@
padding: 64px 24px;
}
- // Icons: ≥1280px — 69px top (top: 90px), 77px bottom (top: 246px, bottom edge: 323px)
- .tb-iot-hub-hero-float-icon {
- width: 69px;
- height: 69px;
-
- &.icon-pos-1 {
- top: 90px;
- left: 106px;
- }
-
- &.icon-pos-2 {
- top: 90px;
- left: auto;
- right: 106px;
- }
-
- &.icon-pos-3 {
- top: 246px;
- left: 28px;
- width: 77px;
- height: 77px;
- }
-
- &.icon-pos-4 {
- top: 246px;
- left: auto;
- right: 28px;
- width: 77px;
- height: 77px;
- }
+ // Cluster shrinks with viewport — keep some gutter on the sides
+ .tb-iot-hub-hero-cluster {
+ top: 30px;
+ width: min(900px, calc(100% - 48px));
}
}
-// ≤959px: only top pair, area width ≤160px (icon 51px + gap + icon 51px)
+// ≤959px: cluster sits closer to the title and uses the full content width
@media #{$mat-lt-md} {
- .tb-iot-hub-hero-float-icon {
- width: 51px;
- height: 51px;
-
- &.icon-pos-1 {
- top: 80px;
- left: calc(50% - 80px);
- }
-
- &.icon-pos-2 {
- top: 80px;
- left: auto;
- right: calc(50% - 80px);
- }
-
- &.icon-pos-3,
- &.icon-pos-4 {
- display: none;
- }
+ .tb-iot-hub-hero-cluster {
+ top: 64px;
+ width: calc(100% - 32px);
}
}
diff --git a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts
index 898230a1e4..53fd0709d9 100644
--- a/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts
+++ b/ui-ngx/src/app/modules/home/pages/iot-hub/iot-hub-home.component.ts
@@ -44,8 +44,7 @@ interface HeroTypeConfig {
type: ItemType;
labelKey: string;
color: string;
- gradientColor: string;
- icons: string[];
+ icon: string;
}
interface SearchResultGroup {
@@ -76,34 +75,28 @@ export class TbIotHubHomeComponent implements OnInit, OnDestroy {
heroTypes: HeroTypeConfig[] = [
{
- type: ItemType.WIDGET, labelKey: 'item.type-widget-plural', color: '#2c9755',
- gradientColor: 'rgba(44, 151, 85, 0.1)',
- icons: ['assets/iot-hub/hero-widget-icon-1.svg', 'assets/iot-hub/hero-widget-icon-2.svg', 'assets/iot-hub/hero-widget-icon-3.svg', 'assets/iot-hub/hero-widget-icon-4.svg']
+ type: ItemType.DEVICE, labelKey: 'item.type-device-plural', color: '#4b63cc',
+ icon: 'assets/iot-hub/hero-device-cluster.svg'
},
{
- type: ItemType.SOLUTION_TEMPLATE, labelKey: 'item.type-solution-template-plural', color: '#2666a9',
- gradientColor: 'rgba(38, 102, 169, 0.1)',
- icons: ['assets/iot-hub/hero-solution-template-icon-1.svg', 'assets/iot-hub/hero-solution-template-icon-2.svg', 'assets/iot-hub/hero-solution-template-icon-3.svg', 'assets/iot-hub/hero-solution-template-icon-4.svg']
+ type: ItemType.SOLUTION_TEMPLATE, labelKey: 'item.type-solution-template-plural', color: '#2b6bb4',
+ icon: 'assets/iot-hub/hero-solution-template-cluster.svg'
},
{
- type: ItemType.DEVICE, labelKey: 'item.type-device-plural', color: '#4b8a79',
- gradientColor: 'rgba(75, 138, 121, 0.1)',
- icons: ['assets/iot-hub/hero-device-icon-1.svg', 'assets/iot-hub/hero-device-icon-2.svg', 'assets/iot-hub/hero-device-icon-3.svg', 'assets/iot-hub/hero-device-icon-4.svg']
+ type: ItemType.WIDGET, labelKey: 'item.type-widget-plural', color: '#2c9755',
+ icon: 'assets/iot-hub/hero-widget-cluster.svg'
},
{
- type: ItemType.CALCULATED_FIELD, labelKey: 'item.type-calculated-field-plural', color: '#006d92',
- gradientColor: 'rgba(0, 109, 146, 0.1)',
- icons: ['assets/iot-hub/hero-calculated-field-icon-1.svg', 'assets/iot-hub/hero-calculated-field-icon-2.svg', 'assets/iot-hub/hero-calculated-field-icon-3.svg', 'assets/iot-hub/hero-calculated-field-icon-4.svg']
+ type: ItemType.CALCULATED_FIELD, labelKey: 'item.type-calculated-field-plural', color: '#3cb4e0',
+ icon: 'assets/iot-hub/hero-calculated-field-cluster.svg'
},
{
- type: ItemType.ALARM_RULE, labelKey: 'item.type-alarm-rule-plural', color: '#4d5fd0',
- gradientColor: 'rgba(77, 95, 208, 0.1)',
- icons: ['assets/iot-hub/hero-dashboard-icon-1.svg', 'assets/iot-hub/hero-dashboard-icon-2.svg', 'assets/iot-hub/hero-dashboard-icon-3.svg', 'assets/iot-hub/hero-dashboard-icon-4.svg']
+ type: ItemType.ALARM_RULE, labelKey: 'item.type-alarm-rule-plural', color: '#d66f2e',
+ icon: 'assets/iot-hub/hero-alarm-rule-cluster.svg'
},
{
- type: ItemType.RULE_CHAIN, labelKey: 'item.type-rule-chain-plural', color: '#95694b',
- gradientColor: 'rgba(149, 105, 75, 0.1)',
- icons: ['assets/iot-hub/hero-rule-chain-icon-1.svg', 'assets/iot-hub/hero-rule-chain-icon-2.svg', 'assets/iot-hub/hero-rule-chain-icon-3.svg', 'assets/iot-hub/hero-rule-chain-icon-4.svg']
+ type: ItemType.RULE_CHAIN, labelKey: 'item.type-rule-chain-plural', color: '#a95ae2',
+ icon: 'assets/iot-hub/hero-rule-chain-cluster.svg'
}
];
diff --git a/ui-ngx/src/assets/iot-hub/hero-alarm-rule-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-alarm-rule-cluster.svg
new file mode 100644
index 0000000000..545e7db89b
--- /dev/null
+++ b/ui-ngx/src/assets/iot-hub/hero-alarm-rule-cluster.svg
@@ -0,0 +1,48 @@
+
diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-cluster.svg
new file mode 100644
index 0000000000..a5206aa4ea
--- /dev/null
+++ b/ui-ngx/src/assets/iot-hub/hero-calculated-field-cluster.svg
@@ -0,0 +1,71 @@
+
diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-1.svg
deleted file mode 100644
index 7734b75c7a..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-1.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-2.svg
deleted file mode 100644
index ac28694c40..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-2.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-3.svg
deleted file mode 100644
index 860997b4a5..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-3.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-4.svg
deleted file mode 100644
index 356d5dece0..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-calculated-field-icon-4.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-1.svg
deleted file mode 100644
index 85f1a39345..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-1.svg
+++ /dev/null
@@ -1,30 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-2.svg
deleted file mode 100644
index ff17afc8fb..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-2.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-3.svg
deleted file mode 100644
index 36ec0aca84..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-3.svg
+++ /dev/null
@@ -1,30 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-4.svg
deleted file mode 100644
index 547826eeb1..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-dashboard-icon-4.svg
+++ /dev/null
@@ -1,30 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-device-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-device-cluster.svg
new file mode 100644
index 0000000000..7e75c744a7
--- /dev/null
+++ b/ui-ngx/src/assets/iot-hub/hero-device-cluster.svg
@@ -0,0 +1,138 @@
+
diff --git a/ui-ngx/src/assets/iot-hub/hero-device-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-device-icon-1.svg
deleted file mode 100644
index 8ef1b628a4..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-device-icon-1.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-device-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-device-icon-2.svg
deleted file mode 100644
index 57e615a72d..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-device-icon-2.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-device-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-device-icon-3.svg
deleted file mode 100644
index 1e7f844ba7..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-device-icon-3.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-device-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-device-icon-4.svg
deleted file mode 100644
index 164db57b9a..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-device-icon-4.svg
+++ /dev/null
@@ -1,30 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-cluster.svg
new file mode 100644
index 0000000000..ee3a4d39de
--- /dev/null
+++ b/ui-ngx/src/assets/iot-hub/hero-rule-chain-cluster.svg
@@ -0,0 +1,72 @@
+
diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-1.svg
deleted file mode 100644
index 53a6019a4d..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-1.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-2.svg
deleted file mode 100644
index 917f875faa..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-2.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-3.svg
deleted file mode 100644
index c5ecbe9b74..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-3.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-4.svg
deleted file mode 100644
index eda7544128..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-rule-chain-icon-4.svg
+++ /dev/null
@@ -1,35 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-cluster.svg
new file mode 100644
index 0000000000..2afd1f2ab8
--- /dev/null
+++ b/ui-ngx/src/assets/iot-hub/hero-solution-template-cluster.svg
@@ -0,0 +1,57 @@
+
diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-1.svg
deleted file mode 100644
index f1d0ee4799..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-1.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-2.svg
deleted file mode 100644
index 9708abc935..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-2.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-3.svg
deleted file mode 100644
index 7151c40b16..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-3.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-4.svg
deleted file mode 100644
index 11a06c0a4f..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-solution-template-icon-4.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-cluster.svg b/ui-ngx/src/assets/iot-hub/hero-widget-cluster.svg
new file mode 100644
index 0000000000..0df6ad4336
--- /dev/null
+++ b/ui-ngx/src/assets/iot-hub/hero-widget-cluster.svg
@@ -0,0 +1,57 @@
+
diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-icon-1.svg b/ui-ngx/src/assets/iot-hub/hero-widget-icon-1.svg
deleted file mode 100644
index 7058c55569..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-widget-icon-1.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-icon-2.svg b/ui-ngx/src/assets/iot-hub/hero-widget-icon-2.svg
deleted file mode 100644
index 905ae06615..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-widget-icon-2.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-icon-3.svg b/ui-ngx/src/assets/iot-hub/hero-widget-icon-3.svg
deleted file mode 100644
index 129999a1a7..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-widget-icon-3.svg
+++ /dev/null
@@ -1,35 +0,0 @@
-
diff --git a/ui-ngx/src/assets/iot-hub/hero-widget-icon-4.svg b/ui-ngx/src/assets/iot-hub/hero-widget-icon-4.svg
deleted file mode 100644
index 4483d53642..0000000000
--- a/ui-ngx/src/assets/iot-hub/hero-widget-icon-4.svg
+++ /dev/null
@@ -1,35 +0,0 @@
-