# Dashboard 2.0: Layout : Fixed : Am I the only one who struggled with this?

**URL:** <https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369>\
**Category:** Dashboard\
**Created:** [12 February 2026 12:42 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369 "2026-02-12T12:42:42Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [12 February 2026 12:42 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/1 "2026-02-12T12:42:42Z")

</div>

Like many others, **I had to migrate my 1.0 dashboard to 2.0**. In Dash 1.0, we had a 1x1 widget with a horizontal size of 48px and a vertical size of 48px, creating a square. **This allowed me to find a compromise between PC and smartphone screens**.

 ![pc smart](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/7/570cc13a33898dd21bca3ac8c5a158058bf83038.jpeg)  
_ **Dashboard 1.0** : PC vs Smartphone : great ! 🤩_

**When I upgraded to Dash 2.0** , I saw the "Fixed Layout" and thought, "Great, we have the same thing as Dash 1.0"... But no !

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/d/bda1f5a55ad7f0e224f3a92b933ac7c802e28b0c.png)  
_Why, in Dash 2.0, with a "Fixed" Layout and a default Theming \> Row Height of 48px (the same settings as Dash 1.0), did you add flexibility below 576px?!_

I understand that Dash 2.0's strength lies in its flexibility (Grid, Notebook, or Tabs modes), but please allow us to have 100% fixed pixels in "Fixed" mode at any screen width!

A 1x1 widget (48px x 48px, or "_(where our default row height is 45px)"_ as seen in the manual)) must be square, not a short or long rectangle.  
 ![flex](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/7/07b2e4075a3905f2a8f1e2a434a4dbd5d0af71cc.gif)  
_I can't do anything with this! We're going from 4 to 3 columns for the same group width. 1x1 widgets are rectangular, or even very rectangular, depending on the screen width which isn't right._

So **I'm racking my brain** trying to optimize the widget's fill as precisely as possible, but it's going to overflow or have a large useless gap when going from 3 to 4 columns, which we didn't ask for!

Please make the "Fixed" x-column mode truly fixed, like in Dash 1.0 with 1x1 squares, not rectangles!

Thank you.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [12 February 2026 15:51 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/2 "2026-02-12T15:51:12Z")

</div>

Oh yeah,  
It's just a CSS to learn...

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/2/c23e3212435469e4ea9cbbf88ea2c48c640f1961.png)

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [12 February 2026 16:12 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/3 "2026-02-12T16:12:33Z")

</div>

See the comment at the start of the [documentation for Fixed layout](https://dashboard.flowfuse.com/layouts/types/fixed.html)  
" _Note: This layout still needs work to make it more flexible and practical, it is advised to use another layout for now._"

@Steve-Mcl I don't see an Issue on github to document the requirements and implement Fixed layout. Should there be one?

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [12 February 2026 22:17 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/4 "2026-02-12T22:17:42Z")

</div>

@hotNipi Thank you for the reply. I was able to go a little further to force the width to the size of my smartphone.

```auto
/* Définit le nombre de colonnes */
.nrdb-layout--flex {
    --layout-columns: 6 !important;
}

/* Force la largeur des groupes à 320px et empêche l'étirement */
.nrdb-ui-group {
    flex: 0 0 320px !important;
    max-width: 320px !important;
    min-width: 320px !important;
}

```

![fixe](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/b/3b563f830c2b67693ef07910f89918aaff116078.gif)  
_This is the behavior I expected from a "Fixed" Layout._

 ![fixe smart](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/e/aebef08913277554e08d6cdb7cd0120a981323a3.jpeg)  
_Smartphone view: readable, usable in 6 columns. No need to switch to 3 columns !_

 ![comp 2 to 1](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/9/d985cc59ae20890048582c4b7f4742e21d92f90a.jpeg)

@hotNipi What do you recommend I do to reduce the border on the right and left so that the widgets touch the edge of the group and distribute the widgets in the remaining space ? Gemini was unable to help me 😆

@Colin

> See the comment at the start of the [documentation for Fixed layout](https://dashboard.flowfuse.com/layouts/types/fixed.html)

Yes, I saw that section at the beginning of the documentation. The goal is to evolve things, or rather, to offer support identical to that of Dash 1.0 for those who, like me, manage complex dashboards and have to rewrite everything… and who struggle to manage flexibility.

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [13 February 2026 07:39 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/5 "2026-02-13T07:39:45Z")

</div>

Padding provides several valuable features, especially in terms of readability, and ignoring it is not recommended. However, the size can be easily changed.

```auto
.nrdb-layout--flex .v-card-text {
    padding-inline: 3px;
}

```

The solution may not be absolute and may lead to side effects

> [@SuperNinja](#):
>
> Gemini was unable to help me

Fancy..

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [13 February 2026 09:25 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/6 "2026-02-13T09:25:00Z")

</div>

Awesome !

![fixe espacé](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/6/16ee009ccf0884fc4d1c672e0a1ea559a12e8e75.gif)  
_here is a real “Fixed” Layout like Dash 1.0_

the CSS code for nostalgic people like me : 😄

```auto
/* Définit le nombre de colonnes */
.nrdb-layout--flex {
    --layout-columns: 6 !important;
}

/* Force la largeur des groupes à 330px et empêche l'étirement */
.nrdb-ui-group {
    flex: 0 0 320px !important;
    max-width: 320px !important;
    min-width: 320px !important;
}

.nrdb-layout--flex .v-card-text {
    padding-inline: 1px;
}

```

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/5/65a044b9769d37b9b732d06cd88364f611a9a177.png)  
_adjusting the theming_

@hotNipi one last thing to conclude this Dash 1.0 like: Do you think it is possible to do:  
 ![colapse](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/3/33e2923011b982634342d2766fbe2222ead29b4a.gif)  
by clicking on the group name or something like that?  
And there, you will be the sun of my day 😆

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [13 February 2026 11:21 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/7 "2026-02-13T11:21:43Z")

</div>

> [@SuperNinja](#):
>
> Do you think it is possible to do

That should be dashboards functionality out of box.

Anyway, I tried and yes it is possible to do.  
But I am already somebody's sun and that is not subject of change.  
Being a sun just alone doesnt pay any of the bills. So I don't share full solution.

Find my post about how to add icons to card header.  
Examine.  
You'll need one per group.

Icon can be clickable.  
On click change the state. (boolean "opened")  
With that state change also change the icon . "mdi-menu-up" -\> mdi-menu-down (and vice versa)

```auto

            toggle(e) {
                if(this.opened){  
                    this.opened = false                
                    this.icon = "mdi-menu-down"
                }
                else{
                    this.opened = true  
                    this.icon = "mdi-menu-up"
                }
            }

```

Forr css add a rule

```auto
.v-card:has(.mdi-menu-down) .v-card-text{
   display:none;
}

```

Happy coding.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [13 February 2026 15:59 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/8 "2026-02-13T15:59:44Z")

</div>

> [@SuperNinja](#):
>
> Do you think it is possible to do:  
> ![colapse](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/3/33e2923011b982634342d2766fbe2222ead29b4a.gif)  
> by clicking on the group name or something like that?

> [@hotNipi](#):
>
> > [@SuperNinja](#):
> >
> > Do you think it is possible to do
> 
> That should be dashboards functionality out of box.

> <https://github.com/FlowFuse/node-red-dashboard/issues/406>
>
> \### Description
> 
> In Dashboard 1.0, it's possible to enable an accordion type int…erface for any \`ui-group\`. This can \_also\_ be controlled with \`open\`/\`close\` controls via the \`ui-control\` node too.
> 
> \### Have you provided an initial effort estimate for this issue?
> 
> I have provided an initial effort estimate

Anyone want to take a stab?

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [13 February 2026 18:15 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/9 "2026-02-13T18:15:19Z")

</div>

> [@hotNipi](#):
>
> Happy coding.

Thanks for your hints, I've come up with this:  
 ![dropdown](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/3/436a3864484d30351153fc2ab5b23984263ebbff.gif)

```auto
[
    {
        "id": "05655f9a44827b05",
        "type": "ui-button",
        "z": "fe2c7bc6.bd49c8",
        "group": "fb354f34b521dacf",
        "name": "delete",
        "label": "",
        "order": 2,
        "width": "1",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "delete",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "red",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 5740,
        "y": 3110,
        "wires": [
            []
        ]
    },
    {
        "id": "83d92044e36c5c81",
        "type": "ui-button",
        "z": "fe2c7bc6.bd49c8",
        "group": "fb354f34b521dacf",
        "name": "<<",
        "label": "",
        "order": 3,
        "width": "1",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "rewind",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "grey",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 5860,
        "y": 3110,
        "wires": [
            []
        ]
    },
    {
        "id": "c904673d8292ee99",
        "type": "ui-button",
        "z": "fe2c7bc6.bd49c8",
        "group": "fb354f34b521dacf",
        "name": "<",
        "label": "",
        "order": 4,
        "width": "1",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "chevron-left",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 5980,
        "y": 3110,
        "wires": [
            []
        ]
    },
    {
        "id": "68970aa8a2ee70f1",
        "type": "ui-button",
        "z": "fe2c7bc6.bd49c8",
        "group": "fb354f34b521dacf",
        "name": ">",
        "label": "",
        "order": 6,
        "width": "1",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "chevron-right",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 6100,
        "y": 3110,
        "wires": [
            []
        ]
    },
    {
        "id": "20e81a36e8ca49bd",
        "type": "ui-button",
        "z": "fe2c7bc6.bd49c8",
        "group": "fb354f34b521dacf",
        "name": ">>",
        "label": "",
        "order": 7,
        "width": "1",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "fast-forward",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "grey",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 6220,
        "y": 3110,
        "wires": [
            []
        ]
    },
    {
        "id": "fd62a7a6e4688110",
        "type": "ui-button",
        "z": "fe2c7bc6.bd49c8",
        "group": "fb354f34b521dacf",
        "name": "",
        "label": "button",
        "order": 8,
        "width": "1",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 6340,
        "y": 3110,
        "wires": [
            []
        ]
    },
    {
        "id": "4b90c0f6cf0d5439",
        "type": "ui-template",
        "z": "fe2c7bc6.bd49c8",
        "group": "fb354f34b521dacf",
        "page": "",
        "ui": "",
        "name": "Colapse home>action",
        "order": 5,
        "width": 0,
        "height": 0,
        "head": "",
        "format": "<template>\n <Teleport v-if=\"mounted\" :to=\"target\">\n <div :class=\"positionClass\" @click=\"toggle\" style=\"cursor: pointer;\">\n <v-icon aria-hidden=\"false\">{{icon}}</v-icon>\n </div>\n </Teleport>\n</template>\n\n<script>\n export default {\n data() { \n return {\n mounted: false,\n target: \"\",\n position: \"right\", //\"left\"\n icon: \"mdi-menu-down\",\n opened: false // AJOUT : état d'ouverture/fermeture\n }\n },\n computed: { \n positionClass: function () {\n return this.position == \"left\" ? \"v-card-item __prepend\" : \"v-card-item__ append\"\n }\n },\n watch: {\n msg: function () {\n //\n }\n },\n mounted(){ \n this.target = '#nrdb-ui-group-'+this.props.group+' .v-card-item'\n this.mounted = true \n },\n methods: { // CORRECTION : la fonction toggle doit être dans methods\n toggle(e) {\n if(this.opened){\n this.opened = false\n this.icon = \"mdi-menu-down\"\n }\n else{\n this.opened = true\n this.icon = \"mdi-menu-up\"\n }\n }\n }\n }\n</script>\n<style>\n .hidden-template {\n display: none !important;\n }\n .v-card:has(.mdi-menu-down) .v-card-text{\n display: none;\n }\n</style>",
        "storeOutMessages": true,
        "passthru": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "hidden-template",
        "x": 5920,
        "y": 3060,
        "wires": [
            []
        ]
    },
    {
        "id": "50b91ca9e9f22f51",
        "type": "ui-dropdown",
        "z": "fe2c7bc6.bd49c8",
        "group": "fb354f34b521dacf",
        "name": "",
        "label": "Select Option:",
        "tooltip": "",
        "order": 1,
        "width": "6",
        "height": "1",
        "passthru": false,
        "multiple": false,
        "chips": false,
        "clearable": false,
        "options": [
            {
                "label": "lab1",
                "value": "val1",
                "type": "str"
            },
            {
                "label": "lab2",
                "value": "val2",
                "type": "str"
            }
        ],
        "payload": "",
        "topic": "topic",
        "topicType": "msg",
        "className": "",
        "typeIsComboBox": true,
        "msgTrigger": "onChange",
        "x": 5930,
        "y": 3160,
        "wires": [
            []
        ]
    },
    {
        "id": "fb354f34b521dacf",
        "type": "ui-group",
        "name": "Action",
        "page": "62f0d5d935a88a45",
        "width": "6",
        "height": 1,
        "order": 3,
        "showTitle": true,
        "className": "",
        "visible": "true",
        "disabled": "false",
        "groupType": "default"
    },
    {
        "id": "62f0d5d935a88a45",
        "type": "ui-page",
        "name": "home",
        "ui": "3dcb17d3fbb77cb1",
        "path": "/page1",
        "icon": "home",
        "layout": "flex",
        "theme": "2da75e915972c00d",
        "breakpoints": [
            {
                "name": "Default",
                "px": "0",
                "cols": "4"
            },
            {
                "name": "Small Desktop",
                "px": "800",
                "cols": "9"
            },
            {
                "name": "Desktop",
                "px": "1024",
                "cols": "12"
            }
        ],
        "order": 1,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "3dcb17d3fbb77cb1",
        "type": "ui-base",
        "name": "Page flowfuse",
        "path": "/dashboard",
        "appIcon": "",
        "includeClientData": true,
        "acceptsClientConfig": [
            "ui-control",
            "ui-notification"
        ],
        "showPathInSidebar": false,
        "headerContent": "page",
        "navigationStyle": "temporary",
        "titleBarStyle": "default",
        "showReconnectNotification": true,
        "notificationDisplayTime": 5,
        "showDisconnectNotification": true,
        "allowInstall": true
    },
    {
        "id": "2da75e915972c00d",
        "type": "ui-theme",
        "name": "Theme black",
        "colors": {
            "surface": "#177278",
            "primary": "#0da3d5",
            "bgPage": "#111111",
            "groupBg": "#333333",
            "groupOutline": "#787878"
        },
        "sizes": {
            "density": "default",
            "pagePadding": "1px",
            "groupGap": "4px",
            "groupBorderRadius": "2px",
            "widgetGap": "3px"
        }
    },
    {
        "id": "444913b779fc80bf",
        "type": "global-config",
        "env": [],
        "modules": {
            "@flowfuse/node-red-dashboard": "1.30.2"
        }
    }
]

```

As soon as I add a dropdown node, it breaks the functionality !?

I need to disable all the "collapse/expand ui-group" templates present for each group on the flow Otherwise, I cannot use the collapse/expand functionality at the same time as dropdown ...I must have messed up somewhere ?

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [13 February 2026 22:19 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/10 "2026-02-13T22:19:26Z")

</div>

I don't have computer to check but if the drop-down uses same icon - mdi-menu-up, then I'd guess it may break the thing easily. Means that the CSS must be made more specific.

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [14 February 2026 12:09 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/11 "2026-02-14T12:09:06Z")

</div>

![drop & colapse](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/e/6ea895318a48287800a35ab1d2968bb2e6c2e14f.gif)

> [@hotNipi](#):
>
> uses same icon - mdi-menu-up, then I'd guess it may break the thing easily. Means that the CSS must be made more specific

You're right !  
Now we need to choose an icon that will never be used in the Flow. Eg. mdi-archive-arrow-down-outline

```auto
<template>
    <Teleport v-if="mounted" :to="target">
        <div :class="positionClass" @click="toggle" style="cursor: pointer;">
            <v-icon aria-hidden="false">{{icon}}</v-icon>
        </div>
    </Teleport>
</template>

<script>
    export default {
        data() {           
            return {
                mounted: false,
                target: "",
                position: "right",
                icon: "mdi-archive-arrow-down-outline",
                opened: false
            }
        },
        computed: {        
            positionClass: function () {
                return this.position == "left" ? "v-card-item __prepend" : "v-card-item__ append"
            },
            // Clé unique pour le localStorage basée sur le groupe
            storageKey: function() {
                return `widget-state-${this.props.group}`
            }
        },
        mounted(){            
            this.target = '#nrdb-ui-group-'+this.props.group+' .v-card-item'
            
            // Restaurer l'état depuis le localStorage
            const savedState = localStorage.getItem(this.storageKey)
            if (savedState !== null) {
                this.opened = savedState === 'true'
                this.icon = this.opened 
                    ? "mdi-archive-arrow-up-outline" 
                    : "mdi-archive-arrow-down-outline"
            }
            
            this.mounted = true            
        },
        methods: {
            toggle(e) {
                this.opened = !this.opened
                this.icon = this.opened 
                    ? "mdi-archive-arrow-up-outline" 
                    : "mdi-archive-arrow-down-outline"
                
                // Sauvegarder l'état dans le localStorage
                localStorage.setItem(this.storageKey, this.opened)
            }
        }
    }
</script>

<style>
    .hidden-template {
        display: none !important;
    }
    .v-card:has(.mdi-archive-arrow-down-outline) .v-card-text{
        display: none;
    }
</style>

```

I think we're doing well ! @joepavitt If you happen to be passing by 😉

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [14 February 2026 12:16 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/12 "2026-02-14T12:16:19Z")

</div>

Takes a day for me to reach the computer....

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [14 February 2026 14:16 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/13 "2026-02-14T14:16:37Z")

</div>

Add a class to the icon so it make the widget kind of unique

```auto
<v-icon class="toggle-icon" @click="toggle" aria-hidden="false">{{icon}}</v-icon>

```

And then upgrade the CSS to make it more specific

```auto
.v-card:has(.toggle-icon.mdi-menu-down ) .v-card-text{
        display:none;
    }

```

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [14 February 2026 21:38 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/14 "2026-02-14T21:38:06Z")

</div>

```auto
<template>
    <Teleport v-if="mounted" :to="target">
        <div :class="[positionClass, 'collapse-control']" @click="toggle" style="cursor: pointer;">
            <v-icon class="toggle-icon" aria-hidden="false" style="color: inherit; opacity: 0.8;">
                {{icon}}
            </v-icon>
        </div>
    </Teleport>
</template>

<script>
    export default {
        data() {           
            return {
                mounted: false,
                target: "",
                position: "right",
                opened: true
            }
        },
        computed: {        
            positionClass: function () {
                return this.position == "left" ? "v-card-item __prepend" : "v-card-item__ append"
            },
            icon: function() {
                return this.opened ? "mdi-menu-up" : "mdi-menu-down"
            },
            storageKey: function() {
                return `widget-state-${this.id}`
            }
        },
        mounted() {            
            // On cible l'élément par l'ID du groupe passé par les props de Node-RED
            this.target = '#nrdb-ui-group-' + this.props.group + ' .v-card-item'
            
            // 1. Restauration de l'état sauvegardé
            const savedState = localStorage.getItem(this.storageKey)
            if (savedState !== null) {
                this.opened = savedState === 'true'
            }

            this.$nextTick(() => {
                const container = document.querySelector(`#nrdb-ui-group-${this.props.group}`)
                if (container) {
                    this.updateState(container)
                }
                this.mounted = true
                
                // 2. Envoi de l'état initial à Node-RED
                this.send({ open: this.opened })
            })
        },
        methods: {
            toggle() {
                this.opened = !this.opened
                localStorage.setItem(this.storageKey, this.opened)
                
                const container = document.querySelector(`#nrdb-ui-group-${this.props.group}`)
                this.updateState(container)

                // 3. Envoi du nouvel état lors du clic
                this.send({ open: this.opened })
            },
            updateState(el) {
                if (!el) return
                if (!this.opened) {
                    el.classList.add('is-collapsed')
                } else {
                    el.classList.remove('is-collapsed')
                }
            }
        },

        // Cette fonction se déclenche juste avant que le widget ne soit supprimé de l'écran
unmounted() {
// On force l'arrêt du flux Node-RED quand on quitte la page
// Mais on ne touche pas au localStorage pour que ça se rouvre au retour
this.send({ open: false });
}
}
</script>

<style>
    /* 1. Cache le conteneur du widget qui porte la classe saisie dans l'UI */
    /* Cela évite qu'un espace vide n'apparaisse dans le groupe */
    .hidden-template {
        display: none !important;
    }

    /* Masquage des éléments quand la classe 'is-collapsed' est présente */
    [id^="nrdb-ui-group-"].is-collapsed .v-card-text,
    [id^="nrdb-ui-group-"].is-collapsed .v-divider {
        display: none !important;
    }
</style>

```

Here's the final version:

- Collapse/expand a group
- Remember the state if the page changes
- Isolated logic if an arrow is present in the Flow
- Invisible template in the Dashboard
- Outputs `msg.open` (true/false on opening/closing and false on page change)

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [16 March 2026 21:38 UTC](https://discourse.nodered.org/t/dashboard-2-0-layout-fixed-am-i-the-only-one-who-struggled-with-this/100369/15 "2026-03-16T21:38:38Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
