Ability to Chat on TikTok Enabled

This commit is contained in:
Rodrigo Emanuel
2025-05-30 16:05:49 -03:00
committed by GitHub
parent 0f21d31476
commit 008aa10318
8 changed files with 550 additions and 299 deletions

View File

@@ -1,4 +1,3 @@
<!DOCTYPE html>
<html lang="en">
<head>
@@ -55,11 +54,33 @@
<div id="chat-input">
<div id="chat-autocomplete-list"></div>
<div class="settings">
<div class="chat-enabler" id="twitch">
<img src="images/logo-twitch.svg" alt="">
<label class="switch"><input type="checkbox" name="chatOnTwitch" checked><span class="slider"></span></label>
</div>
<div class="chat-enabler" id="youtube">
<img src="images/logo-youtube.svg" alt="">
<label class="switch"><input type="checkbox" name="chatOnYoutube" checked><span class="slider"></span></label>
</div>
<div class="chat-enabler" id="tiktok">
<img src="images/logo-tiktok.svg" alt="">
<label class="switch"><input type="checkbox" name="chatOnTiktok"><span class="slider"></span></label>
<span class="hint">Chat only.<br>Needs setup!<br><a href="https://github.com/vortisrd/chatrd/tree/main?tab=readme-ov-file#tiktok-chat-setup" target="_blank">Read More</a></span>
</div>
<div class="chat-enabler" id="kick">
<img src="images/logo-kick.svg" alt="">
<label class="switch"><input type="checkbox" name="chatOnKick"><span class="slider"></span></label>
<span class="hint">Chat only.<br>Needs setup!<br><a href="https://github.com/vortisrd/chatrd/tree/main?tab=readme-ov-file#kickbot-installation-on-streamerbot" target="_blank">Read More</a></span>
</div>
</div>
<form>
<input type="text">
</form>
<button id="chat-input-send"><i class="fa-solid fa-paper-plane"></i></button>
<button id="chat-input-settings"><i class="fa-solid fa-gear"></i></button>
</div>
</div>
</div>

View File

@@ -576,19 +576,29 @@ body {
}
#chat-input #chat-input-send {
right: 60px;
}
#chat-input #chat-input-settings {
right: 20px;
}
#chat-input .settings {
display: inline-block;
display: none;
background: #0c0c0c;
padding: 10px;
padding: 10px 20px;
border-radius: 10px;
position: absolute;
top: -55px;
top: -75px;
right: 0px;
z-index: 11;
box-shadow: 0 0 10px rgba(255,255,255,0.05)
}
#chat-input .settings.active {
display: inline-block;
}
#chat-input .settings::after {
@@ -625,6 +635,16 @@ body {
height: 27px;
}
#chat-input .settings .hint {
color: #FFF;
font-size: 12px;
}
#chat-input .settings .hint a {
color: #ffcc00;
font-weight: bold;
}
/* Hide default HTML checkbox */
#chat-input .settings .switch input[type=checkbox] {
opacity: 1;
@@ -668,7 +688,9 @@ body {
#chat-input #youtube input[type=checkbox]:checked + .slider {
background-color: #FF0000;
}
#chat-input #tiktok input[type=checkbox]:checked + .slider {
background-color: #ff0050;
}
#chat-input #kick input[type=checkbox]:checked + .slider {
background-color: #48d415;
}
@@ -716,7 +738,6 @@ body {
#chat-autocomplete-list div.autocomplete-item {
cursor: pointer;
transition: all ease-in-out 300ms;
}
#chat-autocomplete-list div:not(.autocomplete-item) {

View File

@@ -11,7 +11,6 @@ body {
background-color: #121212;
color: #FFF;
text-align: center;
padding: 30px;
font-size: 16px;
}
@@ -22,12 +21,69 @@ hr {
margin: 20px 0;
}
h2 {
font-size: 20px;
padding: 15px 30px;
border-bottom: 1px solid #222;
margin: 15px 0 0 0;
text-align: left;
position: relative;
}
h2 i {
margin-right: 5px;
}
h2 svg {
width: 26px;
vertical-align: bottom;
fill: #FFF;
}
h2 img {
width: 26px;
vertical-align: bottom;
}
h2 button {
display: none;
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
border: none;
background: black;
text-align: center;
color: #FFF;
cursor: pointer;
font-size: 16px;
padding: 10px;
border-radius: 100px;
}
h2 button i {
margin: 0;
transition: transform 0.3s ease;
}
.accordion-container {
/*max-height: 0;
overflow: hidden;*/
transition: max-height 0.4s ease;
}
#chat-divided {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
gap: 30px;
padding: 30px;
}
#chat-settings { width: 640px; }
@@ -56,16 +112,6 @@ hr {
}
.url-bar input[type=text] {
/*font-family: "Inter", sans-serif;
border: none;
background: #171717;
color: #FFF;
padding: 15px 30px;
border-radius: 10px;
width: 100%;
text-align: center;
outline: none;
font-size: 14px;*/
display: none;
}
@@ -90,33 +136,20 @@ hr {
}
.tab-content {
padding: 20px 30px;
border-radius: 20px;
border-radius: 0 0 20px 20px;
background: #171717;
margin: 20px auto;
margin: 0 auto;
text-align: left;
margin: 0 0 30px 0;
}
.tab-content h2 {
margin-bottom: 15px;
font-size: 20px;
padding: 15px 0px;
border-bottom: 1px solid #222;
.tab-content .wrapper {
padding: 20px 30px;
}
.tab-content h2 i {
margin-right: 5px;
}
.tab-content h2 svg {
width: 26px;
vertical-align: bottom;
fill: #FFF;
}
.tab-content h2 img {
width: 26px;
vertical-align: bottom;
/* When visible */
.tab-content.open {
display: block;
}
.tab-content .setting {

View File

@@ -19,10 +19,10 @@
<div id="chat-settings">
<h1>ChatRD - Setup</h1>
<div class="tab-content" id="config">
<h2><i class="fa-solid fa-screwdriver-wrench"></i> Config</h2>
<div class="tab-content" id="config">
<div class="wrapper">
<div class="setting">
<small id="memberemotesbstatus" class="offline" style="display: inline-block; padding: 10px 20px 10px 10px; background-color: #232323; color: #FFF; border-radius: 10px;">
<i class="fa-solid fa-power-off"></i>
@@ -43,9 +43,15 @@
<div class="setting"><label>Text-to-Speech Events<br><small>Enables TTS for Events.</small></label><label class="switch"><input type="checkbox" name="ttsSpeakerBotEvents"><span class="slider"></span></label></div>
</div>
</div>
<div class="tab-content" id="geral">
<h2><i class="fa-solid fa-gears"></i> General</h2>
<h2><i class="fa-solid fa-gears"></i> General <button class="accordion" data-target="geral"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="geral">
<div class="wrapper">
<div class="setting select">
<label>Language<br><small>Change the chat's events language.</small></label>
<select name="language">
@@ -118,10 +124,16 @@
<div class="setting field"><label>Ignore Chatters<br><small>Separate their names by commas. eg.: StreamLabs,StreamElements</small></label><input type="text" name="ignoreChatters" value="Streamlabs,Streamelements"></div>
<div class="setting field"><label>Hide Chat Msg<br><small>Hides a message after X seconds. (0 disables it)</small></label><input type="number" name="hideAfter" value="0"></div>
</div>
</div>
<div class="tab-content" id="twitch">
<h2><i class="fa-brands fa-twitch"></i> Twitch</h2>
<div class="setting"><label>Chat<br><small>Reads Twitch chat. If <strong>Chat Field is on</strong>, allows to send messages.</small></label><label class="switch"><input type="checkbox" name="showTwitchMessages" checked><span class="slider"></span></label></div>
<h2><i class="fa-brands fa-twitch"></i> Twitch <button class="accordion" data-target="twitch"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="twitch">
<div class="wrapper">
<div class="setting"><label>Chat<br><small>Reads Twitch chat.</small></label><label class="switch"><input type="checkbox" name="showTwitchMessages" checked><span class="slider"></span></label></div>
<div class="setting"><label>Followers</label><label class="switch"><input type="checkbox" name="showTwitchFollows" checked><span class="slider"></span></label></div>
<div class="setting"><label>Bits</label><label class="switch"><input type="checkbox" name="showTwitchBits" checked><span class="slider"></span></label></div>
<div class="setting"><label>Announcements</label><label class="switch"><input type="checkbox" name="showTwitchAnnouncements" checked><span class="slider"></span></label></div>
@@ -134,10 +146,16 @@
<div class="setting"><label>Shared Chat</label><label class="switch"><input type="checkbox" name="showTwitchSharedChat" checked><span class="slider"></span></label></div>
<div class="setting"><label>Statistics<br><small>Shows Twitch Viewers.</small></label><label class="switch"><input type="checkbox" name="showTwitchViewers" checked><span class="slider"></span></label></div>
</div>
</div>
<div class="tab-content" id="youtube">
<h2><i class="fa-brands fa-youtube"></i> YouTube</h2>
<div class="setting"><label>Chat<br><small>Reads YouTube chat. If <strong>Chat Field is on</strong>, allows to send messages.</small></label><label class="switch"><input type="checkbox" name="showYouTubeMessages" checked><span class="slider"></span></label></div>
<h2><i class="fa-brands fa-youtube"></i> YouTube <button class="accordion" data-target="youtube"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="youtube">
<div class="wrapper">
<div class="setting"><label>Chat<br><small>Reads YouTube chat.</small></label><label class="switch"><input type="checkbox" name="showYouTubeMessages" checked><span class="slider"></span></label></div>
<div class="setting"><label>SuperChat</label><label class="switch"><input type="checkbox" name="showYouTubeSuperChats" checked><span class="slider"></span></label></div>
<div class="setting"><label>Super Sticker</label><label class="switch"><input type="checkbox" name="showYouTubeSuperStickers" checked><span class="slider"></span></label></div>
@@ -175,24 +193,35 @@
<textarea name="youTubeCustomEmotes" style="display: none;">{}</textarea>
</div>
</div>
</div>
<div class="tab-content" id="tiktok">
<h2><i class="fa-brands fa-tiktok"></i> TikTok</h2>
<div class="setting"><label>Chat<br><small>Reads TikTok chat. Currently doesn't work with <strong>Chat Field</strong>.</small></label><label class="switch"><input type="checkbox" name="showTikTokMessages" checked><span class="slider"></span></label></div>
<h2><i class="fa-brands fa-tiktok"></i> TikTok <button class="accordion" data-target="tiktok"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="tiktok">
<div class="wrapper">
<div class="setting"><label>Chat<br><small>Reads TikTok chat.</small></label><label class="switch"><input type="checkbox" name="showTikTokMessages" checked><span class="slider"></span></label></div>
<div class="setting"><label>Followers</label><label class="switch"><input type="checkbox" name="showTikTokFollows" checked><span class="slider"></span></label></div>
<div class="setting"><label>Likes<br><small>Show likes in <strong>15</strong> increments. Why? <em>Blame TikFinity!</em> 🤣</small></label><label class="switch"><input type="checkbox" name="showTikTokLikes" checked><span class="slider"></span></label></div>
<div class="setting"><label>Gifts</label><label class="switch"><input type="checkbox" name="showTikTokGifts" checked><span class="slider"></span></label></div>
<div class="setting"><label>Subscriptions</label><label class="switch"><input type="checkbox" name="showTikTokSubs" checked><span class="slider"></span></label></div>
<div class="setting"><label>Statistics<br><small>Shows TikTok Viewers and Likes.</small></label><label class="switch"><input type="checkbox" name="showTikTokStatistics" checked><span class="slider"></span></label></div>
</div>
</div>
<div class="tab-content" id="kick">
<h2>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 800 800">
<polygon class="st0" points="336 111 336 239 401 239 401 175 465 175 465 111 657 111 657 303 593 303 593 367 529 367 529 432 593 432 593 496 657 496 657 689 465 689 465 624 401 624 401 560 336 560 336 689 143 689 143 111 336 111"/>
</svg>
Kick
</h2>
Kick <button class="accordion" data-target="kick"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="kick">
<div class="wrapper">
<div class="setting"><small style="display: inline-block; padding: 10px 20px 10px 10px; background-color: #232323; color: #FFF; border-radius: 10px;"><i class="fa-solid fa-triangle-exclamation"></i> Kick is a <strong>BETA</strong> feature! <strong><a href="https://github.com/vortisrd/chatrd/tree/main#%EF%B8%8F-kick-is-a-beta-feature" target="_blank">Read more</a></strong>.</small></label></div>
@@ -200,7 +229,7 @@
<div class="setting field"><label>Your Kick Username<br><small>Your user handle. It's on kick.com/<strong><u>username</u></strong></small></label><input type="text" name="kickUserName" value=""></div>
<div class="setting"><label>Chat<br><small>Reads Kick chat. If <strong>Chat Field is on</strong>, allows to send messages.</small></label><label class="switch"><input type="checkbox" name="showKickMessages" checked><span class="slider"></span></label></div>
<div class="setting"><label>Chat<br><small>Reads Kick chat.</small></label><label class="switch"><input type="checkbox" name="showKickMessages" checked><span class="slider"></span></label></div>
<div class="setting"><label>Statistics<br><small>Show Kick Viewers. Self-updates each 15 seconds.</small></label><label class="switch"><input type="checkbox" name="showKickViewers" checked><span class="slider"></span></label></div>
@@ -216,10 +245,15 @@
<div class="setting"><label><i class="fa-solid fa-arrow-turn-up"></i> Gifted Bomb<br><small>When a user gifts subs massively.</small></label><label class="switch"><input type="checkbox" name="showKickMassGiftedSubs" checked><span class="slider"></span></label></div>
<div class="setting"><label>Raids</label><label class="switch"><input type="checkbox" name="showKickRaids" checked><span class="slider"></span></label></div>
</div>
</div>
<div class="tab-content" id="extras">
<h2><i class="fa-solid fa-dollar-sign"></i> Donations</h2>
<h2><i class="fa-solid fa-dollar-sign"></i> Donations <button class="accordion" data-target="extras"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="extras">
<div class="wrapper">
<div class="setting"><small style="display: inline-block; padding: 10px 20px 10px 10px; background-color: #232323; color: #FFF; border-radius: 10px;"><i class="fa-solid fa-circle-exclamation"></i> You need to connect Streamlabs to Streamer.Bot. <strong><a target="_blank" href="https://docs.streamer.bot/guide/integrations/streamlabs">Follow the tutorial</a>.</strong></small></label></div>
<div class="setting"></div>
@@ -231,30 +265,45 @@
<div class="setting"><label>Streamlabs Tips</label><label class="switch"><input type="checkbox" name="showStreamlabsDonations" checked><span class="slider"></span></label></div>
<div class="setting"><label>StreamElements Tips</label><label class="switch"><input type="checkbox" name="showStreamElementsTips" checked><span class="slider"></span></label></div>
</div>
</div>
<div class="tab-content" id="patreon">
<h2><i class="fa-brands fa-patreon"></i> Patreon</h2>
<h2><i class="fa-brands fa-patreon"></i> Patreon <button class="accordion" data-target="patreon"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="patreon">
<div class="wrapper">
<div class="setting"><small style="display: inline-block; padding: 10px 20px 10px 10px; background-color: #232323; color: #FFF; border-radius: 10px;"><i class="fa-solid fa-circle-exclamation"></i> You need to connect Patreon to Streamer.Bot. <strong><a target="_blank" href="https://docs.streamer.bot/guide/integrations/patreon">Follow the tutorial</a>.</strong></small></label></div>
<div class="setting"></div>
<div class="setting"><label>Memberships</label><label class="switch"><input type="checkbox" name="showPatreonMemberships" checked><span class="slider"></span></label></div>
</div>
</div>
<div class="tab-content" id="tipeee">
<h2><img src="images/logo-tipeeestream.svg" alt=""> TipeeeStream</h2>
<h2><img src="images/logo-tipeeestream.svg" alt=""> TipeeeStream <button class="accordion" data-target="tipeee"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="tipeee">
<div class="wrapper">
<div class="setting"><small style="display: inline-block; padding: 10px 20px 10px 10px; background-color: #232323; color: #FFF; border-radius: 10px;"><i class="fa-solid fa-circle-exclamation"></i> You need to connect TipeeeStream to Streamer.Bot. <strong><a target="_blank" href="https://docs.streamer.bot/guide/integrations/tipeee-stream">Follow the tutorial</a>.</strong></small></label></div>
<div class="setting"></div>
<div class="setting"><label>Donations</label><label class="switch"><input type="checkbox" name="showTipeeeDonations" checked><span class="slider"></span></label></div>
</div>
</div>
<div class="tab-content" id="kofi">
<h2><img src="images/logo-kofi.svg" alt=""> Ko-Fi</h2>
<h2><img src="images/logo-kofi.svg" alt=""> Ko-Fi <button class="accordion" data-target="kofi"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="kofi">
<div class="wrapper">
<div class="setting"><small style="display: inline-block; padding: 10px 20px 10px 10px; background-color: #232323; color: #FFF; border-radius: 10px;"><i class="fa-solid fa-circle-exclamation"></i> You need to connect Ko-Fi to Streamer.Bot. <strong><a target="_blank" href="https://docs.streamer.bot/guide/integrations/ko-fi">Follow the tutorial</a>.</strong></small></label></div>
<div class="setting"></div>
@@ -263,10 +312,15 @@
<div class="setting"><label>Donations</label><label class="switch"><input type="checkbox" name="showKofiDonations" checked><span class="slider"></span></label></div>
<div class="setting"><label>Orders</label><label class="switch"><input type="checkbox" name="showKofiOrders" checked><span class="slider"></span></label></div>
</div>
</div>
<div class="tab-content" id="fourthwall">
<h2><img src="images/logo-fourthwall.svg" alt=""> Fourthwall</h2>
<h2><img src="images/logo-fourthwall.svg" alt=""> Fourthwall <button class="accordion" data-target="fourthwall"><i class="fa-solid fa-chevron-down"></i></button></h2>
<div class="tab-content accordion-container" id="fourthwall">
<div class="wrapper">
<div class="setting"><small style="display: inline-block; padding: 10px 20px 10px 10px; background-color: #232323; color: #FFF; border-radius: 10px;"><i class="fa-solid fa-circle-exclamation"></i> You need to connect Fourthwall to Streamer.Bot. <strong><a target="_blank" href="https://docs.streamer.bot/guide/integrations/fourthwall">Follow the tutorial</a>.</strong></small></label></div>
<div class="setting"></div>
@@ -288,6 +342,7 @@
<div class="setting field"><label>Gift Command<br><small>Command used to join the Gift Draw. </small></label><input type="text" name="fourthWallGiftDrawCommand" value="!enter"></div>
</div>
</div>
<footer>

View File

@@ -416,14 +416,29 @@ chatInputForm.addEventListener("submit", function(event) {
var chatSendPlatforms = [];
if (showTwitchMessages == true) {
const chatOnTwitch = document.querySelector('#chat-input #twitch input[type=checkbox]').checked;
const chatOnYoutube = document.querySelector('#chat-input #youtube input[type=checkbox]').checked;
const chatOnTiktok = document.querySelector('#chat-input #tiktok input[type=checkbox]').checked;
const chatOnKick = document.querySelector('#chat-input #kick input[type=checkbox]').checked;
console.log(chatOnTwitch,chatOnYoutube,chatOnTiktok,chatOnKick);
if (chatOnTwitch == true) {
chatSendPlatforms.push('twitch');
}
if (showYouTubeMessages == true) {
if (chatOnYoutube == true) {
chatSendPlatforms.push('youtube');
}
if (chatOnTiktok == true) {
chatSendPlatforms.push('tiktok');
}
if (chatOnKick == true) {
chatSendPlatforms.push('kick');
}
chatSendPlatforms = chatSendPlatforms.join(',')
const chatInput = chatInputForm.querySelector("input[type=text]")
@@ -441,7 +456,6 @@ chatInputForm.addEventListener("submit", function(event) {
console.debug('Sending Chat to Streamer.Bot', sendchatstuff);
});
if (showKickMessages == true) {
// Sends Message to Kick that are not commands
if (chatSendPlatforms.includes('kick')) {
if (!chatInputText.startsWith('/')) {
@@ -455,6 +469,19 @@ chatInputForm.addEventListener("submit", function(event) {
});
}
}
// Sends Message to TikTok that are not commands
if (chatSendPlatforms.includes('tiktok')) {
if (!chatInputText.startsWith('/')) {
streamerBotClient.doAction(
{ name : "ChatRD TikTok Messages" },
{
"ttkmessage": chatInputText,
}
).then( (sendchatstuff) => {
console.debug('Sending TikTok Chat to Streamer.Bot', sendchatstuff);
});
}
}
chatInput.value = '';
@@ -588,3 +615,36 @@ document.addEventListener('click', function (e) {
chatcommandslist.innerHTML = '';
}
});
document.addEventListener("DOMContentLoaded", function () {
const settingsPanel = document.querySelector('#chat-input .settings');
chatSettings.addEventListener('click', function () {
settingsPanel.classList.toggle('active');
chatSettings.classList.toggle('active');
});
const checkboxNames = ["chatOnTwitch", "chatOnYouTube", "chatOnTiktok", "chatOnKick"];
// Restore checkbox states from localStorage
checkboxNames.forEach(name => {
const checkbox = document.querySelector(`input[name="${name}"]`);
const savedValue = localStorage.getItem(name);
if (checkbox && savedValue !== null) {
checkbox.checked = savedValue === "true";
}
});
// Save state to localStorage on change
checkboxNames.forEach(name => {
const checkbox = document.querySelector(`input[name="${name}"]`);
if (checkbox) {
checkbox.addEventListener("change", function () {
localStorage.setItem(name, checkbox.checked);
});
}
});
});

View File

@@ -2,7 +2,7 @@ const showPatreonMemberships = getURLParam("showPatreonMemberships", true
const patreonHandlers = {
'Patreon.PledgeCreated': (response) => {
console.debug('Patreon Membersihp', response.data);
console.debug('Patreon Membership', response.data);
patreonMemberships(response.data);
},
};

View File

@@ -354,16 +354,74 @@ async function populateEmoteList() {
const accordionButtons = document.querySelectorAll("button.accordion");
accordionButtons.forEach(button => {
button.addEventListener("click", () => {
const targetId = button.getAttribute("data-target");
const target = document.getElementById(targetId);
const icon = button.querySelector("i");
if (!target || !target.classList.contains("accordion-container")) return;
const isOpen = target.classList.contains("open");
// Fecha todos os outros accordions
document.querySelectorAll(".accordion-container.open").forEach(container => {
if (container !== target) {
container.classList.remove("open");
container.style.maxHeight = null;
const otherButton = document.querySelector(`button.accordion[data-target="${container.id}"]`);
if (otherButton) {
const otherIcon = otherButton.querySelector("i");
if (otherIcon) otherIcon.className = "fa-solid fa-chevron-down";
}
}
});
// Alterna o atual
if (!isOpen) {
target.classList.add("open");
target.style.maxHeight = target.scrollHeight + "px";
if (icon) icon.className = "fa-solid fa-chevron-up";
// Espera a animação terminar para scrollar
target.addEventListener("transitionend", function handler(e) {
if (e.propertyName === "max-height") {
target.removeEventListener("transitionend", handler);
const offset = target.getBoundingClientRect().top + window.scrollY - 60;
window.scrollTo({
top: offset,
behavior: "smooth"
});
}
});
}
else {
target.classList.remove("open");
target.style.maxHeight = null;
if (icon) icon.className = "fa-solid fa-chevron-down";
}
});
});
window.addEventListener('load', () => {
loadSettingsFromLocalStorage();
generateUrl();
pushChangeEvents();
populateEmoteList();
});
document.querySelectorAll('.nav-bar a').forEach(anchor => {
document.querySelectorAll('.nav-bar a').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
@@ -379,7 +437,7 @@ document.querySelectorAll('.nav-bar a').forEach(anchor => {
if (targetElement) {
const offset = 20; // ajusta 20px acima
const offset = 60; // ajusta 20px acima
const y = targetElement.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({
@@ -388,4 +446,7 @@ document.querySelectorAll('.nav-bar a').forEach(anchor => {
});
}
});
});
});

File diff suppressed because one or more lines are too long