Skip to content

Commit

Permalink
Merge branch 'main' into scrollbar-styles
Browse files Browse the repository at this point in the history
  • Loading branch information
tarunsinghofficial authored Mar 27, 2024
2 parents ebd84bd + e71388b commit fa11bf4
Show file tree
Hide file tree
Showing 78 changed files with 770 additions and 984 deletions.
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ GEM
faraday-net_http (3.1.0)
net-http
ffi (1.16.3)
ffi (1.16.3-x64-mingw-ucrt)
hash_with_dot_access (1.2.0)
activesupport (>= 5.0.0, < 8.0)
i18n (1.14.1)
Expand Down Expand Up @@ -107,6 +108,7 @@ GEM
PLATFORMS
arm64-darwin-22
arm64-darwin-23
x64-mingw-ucrt
x86_64-linux

DEPENDENCIES
Expand Down
95 changes: 81 additions & 14 deletions frontend/javascript/code_snippets.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,57 @@
import JSONEditor from "jsoneditor";

export function enableCodeHighlighting() {
document.querySelectorAll('pre code').forEach(block => block.textContent = block.textContent.trim());
hljs.highlightAll();
}

export function copyHeadingDirectLinks() {
const headings = document.querySelectorAll('article h2, article h3, article h4, article h5, article h6, main h2, main h3, main h4, main h5, main h6');

headings.forEach(function (heading) {
const linkIcon = document.createElement('span');
linkIcon.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 22 22" id="direct-heading-link"><g fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"><g stroke="#34D399" stroke-width="2" transform="translate(-981 -1753)"><g transform="translate(982 1754)"><path d="M8 11a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07L9.75 3.18"></path><path d="M12 9a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></g></g></g></svg>`
linkIcon.style.cursor = 'pointer';
linkIcon.style.position = 'relative';
linkIcon.style.left = '10px';
linkIcon.style.display = 'none';

heading.appendChild(linkIcon);

linkIcon.addEventListener('click', function (event) {
event.stopPropagation();
const id = heading.getAttribute('id');
const url = window.location.href.split('#')[0] + '#' + id;
navigator.clipboard.writeText(url);

// Replace the link icon with a checkmark icon
linkIcon.innerHTML = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 12.5L10.150 17L19.5 8" stroke="#34D399" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>`

// Automatically revert the checkmark to the link icon after 2 seconds
setTimeout(function () {
linkIcon.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 22 22" id="direct-heading-link"><g fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"><g stroke="#34D399" stroke-width="2" transform="translate(-981 -1753)"><g transform="translate(982 1754)"><path d="M8 11a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07L9.75 3.18"></path><path d="M12 9a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></g></g></g></svg>`
}, 2000);
});

heading.addEventListener('mouseover', function () {
linkIcon.style.display = 'inline-block'; // Show the link icon on hover
});

heading.addEventListener('mouseout', function () {
linkIcon.style.display = 'none'; // Hide the link icon when not hovering
});
});
}

export function insertCodeSnippetCopyButtons() {
const codeBlocks = document.querySelectorAll('pre code');
codeBlocks.forEach(function(block) {
codeBlocks.forEach(function (block) {
const pre = block.parentNode;
const copyButton = document.createElement('button');
const svgIcon = `<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 11C6 8.17157 6 6.75736 6.87868 5.87868C7.75736 5 9.17157 5 12 5H15C17.8284 5 19.2426 5 20.1213 5.87868C21 6.75736 21 8.17157 21 11V16C21 18.8284 21 20.2426 20.1213 21.1213C19.2426 22 17.8284 22 15 22H12C9.17157 22 7.75736 22 6.87868 21.1213C6 20.2426 6 18.8284 6 16V11Z" stroke="#B4B4B8" stroke-width="1.5"/>
<path d="M6 19C4.34315 19 3 17.6569 3 16V10C3 6.22876 3 4.34315 4.17157 3.17157C5.34315 2 7.22876 2 11 2H15C16.6569 2 18 3.34315 18 5" stroke="#B4B4B8" stroke-width="1.5"/>
const svgIcon = `<svg width="18px" height="18px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 11C6 8.17157 6 6.75736 6.87868 5.87868C7.75736 5 9.17157 5 12 5H15C17.8284 5 19.2426 5 20.1213 5.87868C21 6.75736 21 8.17157 21 11V16C21 18.8284 21 20.2426 20.1213 21.1213C19.2426 22 17.8284 22 15 22H12C9.17157 22 7.75736 22 6.87868 21.1213C6 20.2426 6 18.8284 6 16V11Z" stroke="var(--tw-prose-code)" stroke-width="1.5"/>
<path d="M6 19C4.34315 19 3 17.6569 3 16V10C3 6.22876 3 4.34315 4.17157 3.17157C5.34315 2 7.22876 2 11 2H15C16.6569 2 18 3.34315 18 5" stroke="var(--tw-prose-code)" stroke-width="1.5"/>
</svg>`

copyButton.innerHTML = svgIcon;
Expand All @@ -19,30 +60,56 @@ export function insertCodeSnippetCopyButtons() {
pre.appendChild(copyButton);
pre.style.position = 'relative';
copyButton.style.position = 'absolute';
copyButton.style.right = '5px';
copyButton.style.top = '5px';
copyButton.style.right = '7px';
copyButton.style.top = '10px';
copyButton.style.zIndex = '1';
copyButton.style.border = 'none';
copyButton.style.padding = '5px';
copyButton.style.border = '1px solid var(--tw-prose-code-bg)'; // Add border style
copyButton.style.padding = '10px';
copyButton.style.backdropFilter = 'blur(20px)';
copyButton.style.cursor = 'pointer';
copyButton.style.fontSize = '14px';
copyButton.style.borderRadius='10px';
copyButton.style.boxShadow= 'inset 0 0 0 1.5px var(--tw-prose-code-ring)';

copyButton.addEventListener('click', function() {
copyButton.addEventListener('click', function () {
const contentToCopy = block.innerText;
const tempTextarea = document.createElement('textarea');
tempTextarea.value = contentToCopy;
document.body.appendChild(tempTextarea);
tempTextarea.select();
document.execCommand('copy');
document.body.removeChild(tempTextarea);
const copiedIcon = `<svg width="24px" height="24px" viewBox="0 -0.5 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 12.5L10.167 17L19.5 8" stroke="#B4B4B8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
const copiedIcon = `<svg width="16px" height="16px" viewBox="0 -0.5 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 12.5L10.167 17L19.5 8" stroke="#22b322" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
fill="#B4B4B8"/>
</svg>`;
copyButton.innerHTML = copiedIcon;
setTimeout(function() {
copyButton.innerHTML = copiedIcon;
setTimeout(function () {
copyButton.innerHTML = svgIcon;
}, 2000);
});
});
}
}

export function initializeJSONEditor() {
// Does the page have JSON data?
const jsonTextElt = document.getElementById("json-data");
if (!jsonTextElt) {
return;
}

// Can we turn it into a JS object?
const jsonData = JSON.parse(jsonTextElt.innerText);
if (!jsonData) {
return;
}

// create the editor
const container = document.getElementById("json-editor");
const options = {
mode: 'code',
modes: ['code', 'view'], // allowed modes
}
const editor = new JSONEditor(container, options);
editor.set(jsonData);
}
15 changes: 11 additions & 4 deletions frontend/javascript/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import "$styles/index.css"
import "$styles/syntax-highlighting.css"
import "$styles/index.css";
import "$styles/syntax-highlighting.css";
import "jsoneditor/dist/jsoneditor.min.css";

import {
enableCodeHighlighting,
insertCodeSnippetCopyButtons
insertCodeSnippetCopyButtons,
copyHeadingDirectLinks,
initializeJSONEditor,
} from "./code_snippets";

import {
enableScrollToTop,
saveAndRestoreNavigationPosition
saveAndRestoreNavigationPosition,
setupSidebar
} from "./page_navigation";

import { enableDocSearch } from "./search";
Expand All @@ -19,10 +23,13 @@ import components from "$components/**/*.{js,jsx,js.rb,css}"
console.info("Bridgetown is loaded!")

document.addEventListener("DOMContentLoaded", function(event) {
copyHeadingDirectLinks();
enableCodeHighlighting();
insertCodeSnippetCopyButtons();
initializeJSONEditor();
enableDocSearch('#oba-docs-search-container--desktop');
enableDocSearch('#oba-docs-search-container--mobile');
enableScrollToTop();
saveAndRestoreNavigationPosition();
setupSidebar();
});
40 changes: 40 additions & 0 deletions frontend/javascript/page_navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,46 @@ export function enableScrollToTop() {
});
}

export function setupSidebar() {
const h1Elements = document.querySelectorAll('h1');
const h2Elements = document.querySelectorAll('article h2');
const sidebar = document.querySelector('.sidebar');

function appendSidebarItem(textContent, tagName) {
const newItem = document.createElement('a');
newItem.textContent = textContent;
if (tagName === 'h1') {
newItem.classList.add('sidebar-item', 'text-green-500');
}
else if (tagName === 'h2') {
newItem.classList.add('sidebar-item-h2', 'text-gray-500', 'hover:text-green-400', 'ml-4', 'cursor-pointer');
}
sidebar.appendChild(newItem);

newItem.addEventListener('click', function() {
const currentVersion = newItem.textContent;
const headings = document.querySelectorAll('h2');
let targetElement = null;
headings.forEach(function(heading) {
if (heading.textContent.trim() === currentVersion.trim()) {
targetElement = heading;
}
});
if (targetElement) {
window.scrollTo(0, targetElement.offsetTop - 100);
}
});
}

h1Elements.forEach(function (element) {
appendSidebarItem(element.textContent, 'h1');
});

h2Elements.forEach(function (element) {
appendSidebarItem(element.textContent, 'h2');
});
}

export function saveAndRestoreNavigationPosition() {
var scrollPosition = sessionStorage.getItem('scrollPosition');
if (scrollPosition !== undefined) {
Expand Down
10 changes: 9 additions & 1 deletion frontend/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ button.DocSearch.DocSearch-Button {
}

.DocSearch-Search-Icon {
@apply !h-5 !w-5;
@apply !h-5 !w-5 !text-zinc-400 dark:text-zinc-500;
}

.DocSearch-Button-Placeholder {
Expand Down Expand Up @@ -87,6 +87,14 @@ pre.highlight {
::-webkit-scrollbar-thumb:hover {
background: #333;
}

.jsoneditor {
@apply !border-zinc-300;
}

.jsoneditor-menu {
@apply bg-gradient-to-br;
@apply from-green-600 to-green-700;
}

@tailwind utilities;
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
"postcss-preset-env": "^9.1.2",
"read-cache": "^1.0.0",
"tailwindcss": "^3.4.1"
},
"dependencies": {
"jsoneditor": "^10.0.2"
}
}
15 changes: 9 additions & 6 deletions src/_layouts/default.erb
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
<!doctype html>
<html lang="<%= site.locale %>" class='h-full'>
<!DOCTYPE html>
<html lang="<%= site.locale %>"
x-data="{ themeMode: window.localStorage.getItem('mode') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') }"
:class="{'dark':themeMode=='dark','hidden':!themeMode}"
:data-theme="themeMode"
class='hidden h-full'>
<head>
<%= render "head", locals: { metadata: site.metadata, title: data.title } %>
</head>
<body class="flex min-h-full bg-white antialiased dark:bg-zinc-900" x-data="{nav_open: false}" :class="{'overflow-hidden': nav_open}">
<div class="w-full">
<div class="h-full lg:ml-72 xl:ml-80">
<header
class="contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex"
>
class="contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex">
<div id="navigation-sidebar"class="contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 xl:w-80 lg:dark:border-white/10">
<div class="hidden lg:flex sticky top-0 z-20 py-2 px-6 backdrop-blur-sm dark:backdrop-blur bg-white/[var(--bg-opacity-light)] dark:bg-zinc-900/[var(--bg-opacity-dark)]" style="--bg-opacity-light:0.5;--bg-opacity-dark:0.2">
<%= render 'site_logo' %>
Expand All @@ -23,13 +26,13 @@
<div class="relative flex h-full flex-col px-4 pt-14 sm:px-6 lg:px-8">
<main class="flex-auto">
<article class="flex h-full flex-col pb-10 pt-16">
<div class="flex-auto prose dark:prose-invert break-words [html_:where(&>*)]:mx-auto [html_:where(&>*)]:max-w-2xl [html_:where(&>*)]:lg:mx-[calc(50%-min(50%,theme(maxWidth.lg)))] [html_:where(&>*)]:lg:max-w-3xl">
<div class="flex-auto [html_:where(&>*)]:mx-auto [html_:where(&>*)]:max-w-2xl [html_:where(&>*)]:lg:mx-[calc(50%-min(50%,theme(maxWidth.lg)))] [html_:where(&>*)]:lg:max-w-3xl">
<%= render "bg_checkerboard" %>
<h1><%= data.title %></h1>
<%= content %>
</div>
</article>
</main>
<div class="hidden sidebar text-xs p-4 2xl:flex flex-col fixed top-24 right-12 w-fit max-w-72 h-full"></div>
<%= render "footer", locals: { metadata: site.metadata } %>
</div>
</div>
Expand Down
5 changes: 4 additions & 1 deletion src/_layouts/page.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
layout: default
---

<%= content %>
<div class="prose dark:prose-invert break-words">
<h1><%= data.title %></h1>
<%= content %>
</div>
6 changes: 4 additions & 2 deletions src/_layouts/post.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
layout: default
---

<h1><%= data.title %></h1>
<div class="prose dark:prose-invert break-words">
<h1><%= data.title %></h1>

<%= content %>
<%= content %>
</div>
23 changes: 23 additions & 0 deletions src/_layouts/rest_api.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
layout: default
---

<div class="prose dark:prose-invert break-words">
<h1><%= data.title %></h1>
<p><%= data.description %></p>
<h2>Example Request</h2>
<p>
<a href="<%= data.sample_request_url %>">
<%= data.sample_request_url %>
</a>
</p>

<% if data.example_response_file %>
<h2>Example Response</h2>
<div id="json-data" class='hidden'><%= File.open(File.join(site.root_dir, "src/api/example_responses/", data.example_response_file)).read %></div>
<div class='not-prose'>
<div id="json-editor" style="height:500px"></div>
</div>
<% end %>
<%= content %>
</div>
14 changes: 5 additions & 9 deletions src/_partials/_footer.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
<div class="flex flex-col items-center justify-between gap-5 border-t border-zinc-900/5 pt-8 sm:flex-row dark:border-white/5">
<p class="text-xs text-zinc-600 dark:text-zinc-100">&copy; Open Transit Software Foundation.</p>
<div class="flex gap-4">
<a class="group" href="https://www.github.com/onebusaway">
<span class="sr-only">Follow us on GitHub</span>
<a class="group" href="https://www.github.com/onebusaway" title="Follow us on GitHub">
<svg viewBox="0 0 20 20" aria-hidden="true" class="h-5 w-5 fill-zinc-700 dark:fill-zinc-200 transition group-hover:fill-zinc-900 dark:group-hover:fill-zinc-50">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 1.667c-4.605 0-8.334 3.823-8.334 8.544 0 3.78 2.385 6.974 5.698 8.106.417.075.573-.182.573-.406 0-.203-.011-.875-.011-1.592-2.093.397-2.635-.522-2.802-1.002-.094-.246-.5-1.005-.854-1.207-.291-.16-.708-.556-.01-.567.656-.01 1.124.62 1.281.876.75 1.292 1.948.93 2.427.705.073-.555.291-.93.531-1.143-1.854-.213-3.791-.95-3.791-4.218 0-.929.322-1.698.854-2.296-.083-.214-.375-1.09.083-2.265 0 0 .698-.224 2.292.876a7.576 7.576 0 0 1 2.083-.288c.709 0 1.417.096 2.084.288 1.593-1.11 2.291-.875 2.291-.875.459 1.174.167 2.05.084 2.263.53.599.854 1.357.854 2.297 0 3.278-1.948 4.005-3.802 4.219.302.266.563.78.563 1.58 0 1.143-.011 2.061-.011 2.35 0 .224.156.491.573.405a8.365 8.365 0 0 0 4.11-3.116 8.707 8.707 0 0 0 1.567-4.99c0-4.721-3.73-8.545-8.334-8.545Z"></path>
</svg>
</a>
<a class="group" href="https://play.google.com/store/apps/details?id=com.joulespersecond.seattlebusbot&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1">
<span class="sr-only">Find us on the Google Play Store</span>
<a class="group" href="https://play.google.com/store/apps/details?id=com.joulespersecond.seattlebusbot&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1" title="Find us on the Google Play Store">
<svg class="h-5 w-5 fill-zinc-700 dark:fill-zinc-200 transition group-hover:fill-zinc-900 dark:group-hover:fill-zinc-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="24px" height="24px" baseProfile="basic">
<path d="M38,18c-0.732,0-1.409,0.212-2,0.556V17c0-0.552-0.447-1-1-1H13c-0.553,0-1,0.448-1,1v1.556C11.409,18.212,10.732,18,10,18 c-2.206,0-4,1.794-4,4v10c0,2.206,1.794,4,4,4c0.732,0,1.409-0.212,2-0.556V36c0,1.654,1.346,3,3,3v5c0,2.206,1.794,4,4,4 s4-1.794,4-4v-5h2v5c0,2.206,1.794,4,4,4s4-1.794,4-4v-5c1.654,0,3-1.346,3-3v-0.556C36.591,35.788,37.268,36,38,36 c2.206,0,4-1.794,4-4V22C42,19.794,40.206,18,38,18z"/>
<path d="M19,46c-2.206,0-4-1.794-4-4V32c0-2.206,1.794-4,4-4s4,1.794,4,4v10C23,44.206,21.206,46,19,46z M19,30 c-1.103,0-2,0.897-2,2v10c0,1.103,0.897,2,2,2s2-0.897,2-2V32C21,30.897,20.103,30,19,30z"/>
Expand All @@ -27,21 +25,19 @@
<circle cx="28.5" cy="10.5" r="1.5"/>
</svg>
</a>
<a class="group" href="https://apps.apple.com/in/app/onebusaway/id329380089">
<span class="sr-only">Find us on the App Store</span>
<a class="group" href="https://apps.apple.com/in/app/onebusaway/id329380089" title="Find us on the App Store">
<svg class="h-5 w-5 fill-zinc-700 dark:fill-zinc-200 transition group-hover:fill-zinc-900 dark:group-hover:fill-zinc-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" width="24px" height="24px">
<path d="M25.565,9.785c-0.123,0.077-3.051,1.702-3.051,5.305c0.138,4.109,3.695,5.55,3.756,5.55 c-0.061,0.077-0.537,1.963-1.947,3.94C23.204,26.283,21.962,28,20.076,28c-1.794,0-2.438-1.135-4.508-1.135 c-2.223,0-2.852,1.135-4.554,1.135c-1.886,0-3.22-1.809-4.4-3.496c-1.533-2.208-2.836-5.673-2.882-9 c-0.031-1.763,0.307-3.496,1.165-4.968c1.211-2.055,3.373-3.45,5.734-3.496c1.809-0.061,3.419,1.242,4.523,1.242 c1.058,0,3.036-1.242,5.274-1.242C21.394,7.041,23.97,7.332,25.565,9.785z M15.001,6.688c-0.322-1.61,0.567-3.22,1.395-4.247 c1.058-1.242,2.729-2.085,4.17-2.085c0.092,1.61-0.491,3.189-1.533,4.339C18.098,5.937,16.488,6.872,15.001,6.688z"/>
</svg>
</a>
<a class="group" href="https://opentransitsoftwarefoundation.org/blog/">
<span class="sr-only">Read our Blog</span>
<a class="group" href="https://opentransitsoftwarefoundation.org/blog/" title="Read our Blog">
<svg class="h-5 w-5 fill-zinc-700 dark:fill-zinc-200 transition group-hover:fill-zinc-900 dark:group-hover:fill-zinc-50" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="24px" height="24px">
<path d="M 9 4 C 6.239 4 4 6.239 4 9 L 4 41 C 4 43.761 6.239 46 9 46 L 41 46 C 43.761 46 46 43.761 46 41 L 46 9 C 46 6.239 43.761 4 41 4 L 9 4 z M 20 12 L 25 12 C 29.42 12 33.033 15.632547 33 20.060547 C 32.991 21.141547 33.919 22 35 22 L 36 22 C 37.105 22 38 22.895 38 24 L 38 30 C 38 34.4 34.4 38 30 38 L 20 38 C 15.6 38 12 34.4 12 30 L 12 25 L 12 20 C 12 15.6 15.6 12 20 12 z M 20 18 C 18.9 18 18 18.9 18 20 C 18 21.1 18.9 22 20 22 L 25 22 C 26.1 22 27 21.1 27 20 C 27 18.9 26.1 18 25 18 L 20 18 z M 20 28 C 18.9 28 18 28.9 18 30 C 18 31.1 18.9 32 20 32 L 30 32 C 31.1 32 32 31.1 32 30 C 32 28.9 31.1 28 30 28 L 20 28 z"/>
</svg>
</a>
</div>
</div>
<button id="scrollToTopBtn" title="Scroll to Top" class="fixed bottom-4 lg:bottom-8 right-4 lg:right-8 z-50 shadow-md bg-green-500 dark:bg-green-500/70 text-white cursor-pointer px-4 py-2 rounded-lg text-lg hidden">
<button id="scrollToTopBtn" title="Scroll to Top" class="fixed bottom-4 lg:bottom-8 right-4 lg:right-8 z-50 shadow-md bg-green-500 dark:bg-green-500/70 dark:text-white bg-opacity-50 backdrop-blur-md cursor-pointer rounded-full text-lg hidden">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8">
<path stroke-linecap="round" stroke-linejoin="round" d="m15 11.25-3-3m0 0-3 3m3-3v7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
Expand Down
Loading

0 comments on commit fa11bf4

Please sign in to comment.