New - unofficial - feature: TABS - Hide/Show multiple blocks horizontally

Hi Matthieu,

I understand you have things to do… So to make things easier I made an example website: https://adina2775.softr.app

In creating this example, I noticed the excess space is caused by the largest block AFTER a footer has been added. So it somehow has to do with this footer.

What e-mail address can I send the invitation to?

Sent by direct message.

Update: No large space or huge space seen during the test, everyhting works fine on my end.

Hi, Great work! Can you advise how I link the buttons to the actual blocks. Somehow, i have difficulties to figure this out. Could you provide an example? Also how do i make the content of the blocks variable based on the linked Record.

For example. I have a page with “List with vertical cards and tag” block. These card link into detail pages where i created this tabs section. I have data pulling from airtable into these detail pages.

Thanks in advance

Important update

This is true for the tab feature as well as for any other custom code using javascript.

From now on, as blocks load faster than the footer code is being executed, all javascript codes should be inside the header custom code of the page level (same for app level by the way), unless a third party tool tells you to insert a code in the footer.

There might be some exceptions but as soon as you use window.addEventListener('block-loaded-BLOCKID', () => { in a code => header.
As soon as you use javascript that should be run on page load => header.

Otherwise the script might work 50 to 70% of the time… Which is not ideal

2 Likes

Great job Matthieu!! That’s really helpful. Thank you so much!

I changed the blocked-loaded listener to: window.addEventListener('DOMContentLoaded', () => {
and seems to be behaving.

Great custom code, I have been using it a lot in one of my projects! Surprised it isn´t a standard feature in Softr.

There is one thing that I have noticed that is behaving a bit weird when it comes to Calendar blocks. If the calendar block is connected to the first button, and therefore is displayed right away, everything works as it´s supposed to. But if the calendar block is displayed first when pressing another button, the items in the calendar are “minimized” to “X more” as the block does when there is a lot of items on the same date, even though there´s only one item. Triggering for example a filter so the calendar reloads fixes it.

See images below before and after triggering a filter in the calendar block:

image
image

Hi,

I know exactly what’s wrong, it’s specific to the calendar block.

Can you show your script for tabs (and tell me what is the calendar ID in this script) so I can quickly debug it?

Sure thing, thanks!
List3 (yes, I am lazy with the naming of blocks :grinning:) is the calendar block.

<!DOCTYPE html>
<html>
<head>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Inter&display=swap');
        
         .button-group {
            display: flex;
            justify-content: center;
        }

        .button {
            background-color: #4B664D;
            color: white;
            font-family: 'Inter', sans-serif;
            font-size: 15px; 
            padding: 10px 20px; 
            margin-right: 30px;
            padding-top: 8px;
            padding-bottom: 8px;
            border-radius: 14px;
            border: none;
            cursor: pointer;
        }
        
        .button:hover {
        background-color: #f5e507;
        color: #182939;
       }
        
        .button:focus {
        outline: none;
       }

        .button:active, .active {
            background-color: #f5e507;
            color: #182939;
            outline: none;
        }

        @media (max-width: 480px) {
            .button-group {
                display: flex;
                flex-direction: column;
                align-items: flex-start;
            }

            .button {
                display: none;
            }

            .dropdown {
                display: block;
                width: 100%;
                margin-top: 10px;
                padding: 10px 20px; 
                border-radius: 14px;
                border: none;
                background-color: #4B664D;
                color: white;
                font-family: 'Inter', sans-serif;
                font-size: 15px;
                cursor: pointer;
            }
        }

        @media (min-width: 481px) {
            .button-group {
                display: flex;
                justify-content: center;
            }

            .dropdown {
                display: none;
            }
        }
    </style>
</head>
<body>
    <div class="button-group">
        <button class="button active" onclick="runButton1Script()">Arbete kommande vecka</button>
        <button class="button" onclick="runButton2Script()">Företagsinfo</button>
        <button class="button" onclick="runButton3Script()">Alla arbeten</button>
        <select class="dropdown" onchange="runDropdownScript(this.value)">
            <option value="button1">Arbete kommande vecka</option>
            <option value="button2">Företagsinfo</option>
            <option value="button3">Alla arbeten</option>
        </select>
    </div>
    <script>
        const buttons = document.querySelectorAll('.button');
        buttons.forEach(button => {
            button.addEventListener('click', function() {
                buttons.forEach(b => b.classList.remove('active'));
                this.classList.add('active');
            });
        });

        function runDropdownScript(value) {
            switch(value) {
                case 'button1':
                    runButton1Script();
                    break;
                case 'button2':
                    runButton2Script();
                    break;
                case 'button3':
                    runButton3Script();
                    break;
                default:
                    break;
            }
        }
    </script>
</body>
</html>

<script>
    // hide blocks 
    window.addEventListener('DOMContentLoaded', (event) => {
        document.getElementById("list1").style.display = "block";
        document.getElementById("list2").style.display = "none";
        document.getElementById("list3").style.display = "none"
    });

    function runButton1Script() {
        document.getElementById("list1").style.display = "block";
        document.getElementById("list2").style.display = "none";
        document.getElementById("list3").style.display = "none";;
        console.log("Button 1 clicked"); 
    }

         function runButton2Script() {
        document.getElementById("list2").style.display = "block";
        document.getElementById("list1").style.display = "none";
        document.getElementById("list3").style.display = "none";
        console.log("Button 2 clicked");
    }
          function runButton3Script() {
        document.getElementById("list3").style.display = "block";
        document.getElementById("list1").style.display = "none";
        document.getElementById("list2").style.display = "none";
        console.log("Button 3 clicked");
    }

</script>
</html>```

Try this one, replace the last script by:
I added window.dispatchEvent(new CustomEvent('reload-block-list3')); , it’s mandatory for the calendar block when using the tabs feature.

<script>
    // hide blocks 
    window.addEventListener('DOMContentLoaded', (event) => {
        document.getElementById("list1").style.display = "block";
        document.getElementById("list2").style.display = "none";
        document.getElementById("list3").style.display = "none"
    });

    function runButton1Script() {
        document.getElementById("list1").style.display = "block";
        document.getElementById("list2").style.display = "none";
        document.getElementById("list3").style.display = "none";;
        console.log("Button 1 clicked"); 
    }

         function runButton2Script() {
        document.getElementById("list2").style.display = "block";
        document.getElementById("list1").style.display = "none";
        document.getElementById("list3").style.display = "none";
        console.log("Button 2 clicked");
    }
          function runButton3Script() {
        document.getElementById("list3").style.display = "block";
        document.getElementById("list1").style.display = "none";
        document.getElementById("list2").style.display = "none";
        window.dispatchEvent(new CustomEvent('reload-block-list3'));
        console.log("Button 3 clicked");
    }

</script>

Works great, thank you!

2 Likes

@matthieu_chateau Thanks for this solution, this works great on the calendar block, which we were having issues with as well.

We’re seeing the same behavior on the open street map block but the reload event doesn’t seem to have any effect on that block type. Does it require a different syntax?

Code below and screenshot of the behavior also attached.

    <style>
@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap');
         .button-group {
            display: flex;
            justify-content: center;
        }

        .button {
            font-family: 'Inter', sans-serif;
            font-size: 14px; 
            font-weight: 500;
            //border-radius: 0;
            border-top-left-radius: 10px;
            border-top-right-radius: 10px;
            border: none;
            cursor: pointer;
            background-color: white;
            color: #2F3133;
            outline: none;
            border: none;
            text-align: center;
            border-bottom: 2px solid #D4D4D4;
            border-left: 2px solid #D4D4D4;
            border-right: 2px solid #D4D4D4;
            border-top: 2px solid #D4D4D4;
            transition .3s;
            margin-right: 0em;
            margin-left: 0em;
            padding-right: 20px;
            padding-left: 20px;
            padding-bottom: 8px;
            padding-top: 8px;
            }

        .button:active, .active {
           font-size: 14px; 
            font-weight: bold;
            //border-radius: 0;
            border-top-left-radius: 10px;
            border-top-right-radius: 10px;
            border: none;
            cursor: pointer;
            background-color: transparent;
            color: #2F3133;
            outline: none;
            border: none;
            text-align: center;
            //border-bottom: 2px solid gray;
            border-left: 1px solid #C8C8C8;
            border-right: 1px solid #C8C8C8;
            border-top: 1px solid #C8C8C8;
            transition .3s;
            margin-right: 0em;
            margin-left: 0em;
            padding-right: 20px;
            padding-left: 20px;
            padding-bottom: 8px;
            padding-top: 8px;
                     
        }
        
        button:focus {outline:0;}
        
        button:hover
    </style>
    <div class="button-group">
        <button class="button active" onclick="runButton1Script()">Projects</button>
        <button class="button" onclick="runButton2Script()">Project Map</button>
        <button class="button" onclick="runButton6Script()">Projects by Company</button>
        <button class="button" onclick="runButton3Script()">Project Stats</button>
        <button class="button" onclick="runButton4Script()">Calendar View</button>
        <button class="button" onclick="runButton5Script()">Gantt View</button>
    </div>
     <script>
    const buttons = document.querySelectorAll('.button');
        buttons.forEach(button => {
        button.addEventListener('click', function() {
            buttons.forEach(b => b.classList.remove('active'));
            this.classList.add('active');
        });
    });
</script>

<script>
    // hide blocks
    window.addEventListener('DOMContentLoaded', (event) => {
        document.getElementById("block2").style.display = "block";
        document.getElementById("block1").style.display = "none";
        document.getElementById("chart1").style.display = "none";
        document.getElementById("chart2").style.display = "none";
        document.getElementById("chart3").style.display = "none";
        document.getElementById("chart5").style.display = "none";
        document.getElementById("chart6").style.display = "none";
        document.getElementById("chart7").style.display = "none";
        document.getElementById("calendar1").style.display = "none";
        document.getElementById("gantt1").style.display = "none";
        document.getElementById("projects").style.display = "none";
    });
    
    function runButton1Script() {
        document.getElementById("block2").style.display = "block";
        document.getElementById("block1").style.display = "none";
        document.getElementById("chart1").style.display = "none";
        document.getElementById("chart2").style.display = "none";
        document.getElementById("chart3").style.display = "none";
        document.getElementById("chart5").style.display = "none";
        document.getElementById("chart6").style.display = "none";
        document.getElementById("chart7").style.display = "none";
        document.getElementById("calendar1").style.display = "none";
        document.getElementById("gantt1").style.display = "none";
        document.getElementById("projects").style.display = "none";
        console.log("Button 1 clicked"); 
    }
    
    function runButton2Script() {
        window.dispatchEvent(new CustomEvent('reload-block-block1'));
        document.getElementById("block1").style.display = "block";
        document.getElementById("block2").style.display = "none";
        document.getElementById("chart1").style.display = "none";
        document.getElementById("chart2").style.display = "none";
        document.getElementById("chart3").style.display = "none";
        document.getElementById("chart5").style.display = "none";
        document.getElementById("chart6").style.display = "none";
        document.getElementById("chart7").style.display = "none";
        document.getElementById("calendar1").style.display = "none";
        document.getElementById("gantt1").style.display = "none";
        document.getElementById("projects").style.display = "none";
        console.log("Button 2 clicked"); 
    }
    
    function runButton3Script() {
        document.getElementById("chart1").style.display = "block";
        document.getElementById("chart2").style.display = "block";
        document.getElementById("chart3").style.display = "block";
        document.getElementById("chart5").style.display = "block";
        document.getElementById("chart6").style.display = "block";
        document.getElementById("chart7").style.display = "block";
        document.getElementById("block1").style.display = "none";
        document.getElementById("block2").style.display = "none";
        document.getElementById("calendar1").style.display = "none";
        document.getElementById("gantt1").style.display = "none";
        document.getElementById("projects").style.display = "none";
        console.log("Button 3 clicked"); 
    }
    
    function runButton4Script() {
        window.dispatchEvent(new CustomEvent('reload-block-calendar1'));
        document.getElementById("calendar1").style.display = "block";
        document.getElementById("chart1").style.display = "none";
        document.getElementById("chart2").style.display = "none";
        document.getElementById("chart3").style.display = "none";
        document.getElementById("chart5").style.display = "none";
        document.getElementById("chart6").style.display = "none";
        document.getElementById("block1").style.display = "none";
        document.getElementById("block2").style.display = "none";
        document.getElementById("chart7").style.display = "none";
        document.getElementById("gantt1").style.display = "none";
        document.getElementById("projects").style.display = "none";
        console.log("Button 4 clicked"); 
    }
    
    function runButton5Script() {
        document.getElementById("gantt1").style.display = "block";
        document.getElementById("calendar1").style.display = "none";
        document.getElementById("chart1").style.display = "none";
        document.getElementById("chart2").style.display = "none";
        document.getElementById("chart3").style.display = "none";
        document.getElementById("chart5").style.display = "none";
        document.getElementById("chart6").style.display = "none";
        document.getElementById("block1").style.display = "none";
        document.getElementById("block2").style.display = "none";
        document.getElementById("chart7").style.display = "none";
        document.getElementById("projects").style.display = "none";
        console.log("Button 5 clicked"); 
    }
    
    function runButton6Script() {
        document.getElementById("projects").style.display = "block";
        document.getElementById("gantt1").style.display = "none";
        document.getElementById("calendar1").style.display = "none";
        document.getElementById("chart1").style.display = "none";
        document.getElementById("chart2").style.display = "none";
        document.getElementById("chart3").style.display = "none";
        document.getElementById("chart5").style.display = "none";
        document.getElementById("chart6").style.display = "none";
        document.getElementById("block1").style.display = "none";
        document.getElementById("block2").style.display = "none";
        document.getElementById("chart7").style.display = "none";
        console.log("Button 6 clicked"); 
    }
</script>