Skip to content

Instantly share code, notes, and snippets.

@fabriziogiordano
Last active October 6, 2024 19:25
Show Gist options
  • Save fabriziogiordano/a22953f2bb2340b792c91f10b93637da to your computer and use it in GitHub Desktop.
Save fabriziogiordano/a22953f2bb2340b792c91f10b93637da to your computer and use it in GitHub Desktop.
HammerSpoon - Calendar Menubar

Add current clock on menubar an when clicked it show a quick view of the calendar.

<style>
html {
background-color: transparent;
max-width: 300px;
overflow: hidden;
border-radius: 16px;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica", "Arial", sans-serif;
margin: 0;
padding: 10px;
box-sizing: border-box;
background-color: #1E1E1E;
color: white;
border-radius: 16px;
font-size: 8px;
color: #999;
border: 1px solid #555555;
overflow: hidden;
}
table {
border-collapse: collapse;
font-size: 10px;
margin: 0 auto;
}
th,
td {
text-align: center;
}
th {
background-color: #333333;
padding: 8px 0;
}
td {
background-color: #1E1E1E;
color: #ffffff;
width: 30px;
height: 30px;
}
.today {
background-color: #007AFF;
font-weight: bold;
color: #ffffff;
border-radius: 100%;
}
.nav-buttons {
width: 100%;
text-align: center;
margin-top: 10px;
display: flex;
flex-direction: row;
justify-content: space-between;
font-size: 6px;
cursor: pointer;
}
.nav-buttons button {
border-radius: 3px;
}
button {
background-color: #333333;
color: white;
border: none;
padding: 10px;
cursor: pointer;
}
button:hover {
background-color: #555555;
}
</style>
<div id="calendar"></div>
<div class="nav-buttons">
<button onclick="changeMonth(-1)">Prev</button>
<button onclick="changeMonth(1)">Next</button>
</div>
<script>
const currentYear = new Date().getFullYear();
let currentMonth = new Date().getMonth() + 1; // JavaScript months are 0-based, so we add 1
function generateCalendar(year, month) {
const date = new Date(year, month - 1, 1); // Adjusting month to 0-based for JS Date
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const header = '<h1 style="text-align: center;">' + monthNames[month - 1] + ' ' + year + '</h1>';
let table = '<table><tr>';
for (var i = 0; i < 7; i++) {
table += '<th>' + days[i] + '</th>';
}
table += '</tr><tr>';
for (let i = 0; i < date.getDay(); i++) {
table += '<td></td>';
}
const today = new Date();
while (date.getMonth() === month - 1) {
const cellClass = (date.getDate() === today.getDate() && date.getMonth() === today.getMonth() && date.getFullYear() === today.getFullYear()) ? 'today' : '';
table += '<td class="' + cellClass + '">' + date.getDate() + '</td>';
if (date.getDay() === 6) {
table += '</tr><tr>';
}
date.setDate(date.getDate() + 1);
}
table += '</tr></table>';
document.getElementById('calendar').innerHTML = header + table;
}
// Function to change the month (either forward or backward)
function changeMonth(offset) {
currentMonth += offset;
// Adjust the year if necessary
if (currentMonth > 12) {
currentMonth = 1;
currentYear++;
} else if (currentMonth < 1) {
currentMonth = 12;
currentYear--;
}
// Re-generate the calendar with updated month and year
generateCalendar(currentYear, currentMonth);
}
// Generate the initial calendar
generateCalendar(currentYear, currentMonth);
</script>
-- Create a menu bar item
local menubar = hs.menubar.new()
local calendarWindow = nil
-- Function to update the clock
local function updateClock()
-- local date = os.date("%a %b %d %H:%M"):gsub(" 0", " ")
-- menubar:setTitle(date)
menubar:setTitle("◳")
end
-- Function to sync the timer with the start of the next minute
local function syncTimer()
local now = os.time()
local seconds = os.date("*t", now).sec
local delay = 60 - seconds
hs.timer.doAfter(delay, function()
updateClock()
-- Set up the recurring timer after syncing
hs.timer.doEvery(60, updateClock)
end)
end
-- Function to create or toggle the calendar
local function toggleCalendar()
if calendarWindow and calendarWindow:isVisible() then
print("Hiding calendar window")
calendarWindow:delete()
calendarWindow = nil
else
if not calendarWindow then
print("Creating new calendar window")
-- Get the screen and frame details
local screen = hs.screen.mainScreen()
local screenFrame = screen:frame()
local menuBarHeight = 1
-- Calculate position for the calendar window
local calendarWidth = 250
local calendarHeight = 308
local calendarX = screenFrame.x - 2 + screenFrame.w - calendarWidth -- Right-aligned
local calendarY = screenFrame.y + menuBarHeight -- Below the menu bar
calendarWindow = hs.webview.new({
x = calendarX,
y = calendarY,
w = calendarWidth,
h = calendarHeight
})
if not calendarWindow then
print("Failed to create webview")
return
end
-- Enable interaction with the webview
calendarWindow:allowTextEntry(true)
calendarWindow:allowGestures(true)
calendarWindow:allowNewWindows(false)
-- Set the webview window level and behavior
calendarWindow:level(hs.drawing.windowLevels.overlay)
-- calendarWindow:behavior(hs.webview.windowBehavior.canJoinAllSpaces + hs.webview.windowBehavior.stationary)
-- Set the HTML content for the calendar
local URL = "file://" .. hs.configdir .. "/calendar.html"
print(hs.configdir)
calendarWindow:url(URL)
calendarWindow:transparent(true)
end
print("Showing calendar window")
calendarWindow:show()
end
end
-- Set click callback for the menubar
menubar:setClickCallback(toggleCalendar)
-- Initial update and start the timer
updateClock()
syncTimer()
print("Script loaded successfully")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment