Skip to content

Instantly share code, notes, and snippets.

@BorisAnthony
Created October 9, 2024 07:56
Show Gist options
  • Save BorisAnthony/783de124610cd4de6e3d6491f8f957fe to your computer and use it in GitHub Desktop.
Save BorisAnthony/783de124610cd4de6e3d6491f8f957fe to your computer and use it in GitHub Desktop.
Übersicht "TimeZoneStrip" JSX widget
/**
* Übersicht "TimeZoneStrip" JSX widget
* [email protected] / 2024-10-09
* MIT Licensed
* Based on https://www.reddit.com/r/Ubersicht/comments/1fdp5bu/widget_based_on_the_worldtimebuddy/
*/
import { css, run } from "uebersicht";
const timezones = [
{ name: "JST", timezone: "Asia/Tokyo" },
{ name: "CET", timezone: "Europe/Berlin" },
{ name: "UTC", timezone: "UTC" },
{ name: "EST", timezone: "America/New_York" },
{ name: "PST", timezone: "America/Los_Angeles" },
];
const timezones_count = timezones.length;
export const command = async (dispatch) => {
const times = await Promise.all(
timezones.map(async (tz) => {
const date = await run(`TZ=${tz.timezone} date +'%H %d %b'`);
const [hour, day, month] = date.trim().split(" ");
return { ...tz, hour: parseInt(hour), day, month };
})
);
dispatch({ type: "UPDATE_TIMES", times });
};
export const refreshFrequency = 60000; // Update every minute
export const initialState = { times: [] };
export const updateState = (event, previousState) => {
if (event.type === "UPDATE_TIMES") {
return { ...previousState, times: event.times };
}
return previousState;
};
const HourBox = ({ content, type, isCurrentHour }) => {
let boxStyle = hourBox;
let textColor = "";
switch (type) {
case "date":
boxStyle += ` ${dateBox}`;
textColor = `rgb(255 255 255 / ${isCurrentHour ? 1 : 0.8})`;
break;
case "earlyMorning":
boxStyle += ` ${earlyMorning}`;
textColor = `rgb(255 255 255 / ${isCurrentHour ? 1 : 0.5})`;
break;
case "morning":
boxStyle += ` ${morning}`;
textColor = `rgb(255 255 255 / ${isCurrentHour ? 1 : 0.4})`;
break;
case "dayNight":
boxStyle += ` ${dayNight}`;
textColor = `rgb(255 255 255 / ${isCurrentHour ? 1 : 0.7})`;
break;
case "evening":
// boxStyle += ` ${eveNing}`;
textColor = `rgb(255 255 255 / ${isCurrentHour ? 1 : 0.6})`;
break;
case "tzName":
boxStyle += ` ${timezoneName}`;
break;
}
if (isCurrentHour) {
boxStyle += ` ${currentHour}`;
}
return (
<div className={boxStyle} style={{ color: textColor }}>
{content}
</div>
);
};
export const render = ({ times }) => {
if (times.length === 0) return <div>Loading...</div>;
const hoursBeforeCurrent = 0; // Show 11 hours before the current hour
return (
<div className={container}>
<div className={widgetContent}>
<div className={rowsWrapper}>
{times.map((tz) => {
const watTimezone = (tz.name === "CET") ? currentTimezone : otherTimezone;
// const gradientOffset = ((24 - tz.hour) + 12) * 36;
const gradientOffset = tz.hour * 36;
// console.log(tz.name + " - " + tz.hour + " - " + gradientOffset);
return (
<div key={tz.name} className={timezoneRow}>
<div className={hoursContainerWrapper}>
<div
className={hoursContainer + " " + watTimezone}
style={{
backgroundImage:
`linear-gradient(
180deg in oklab,
hsl(240 50% 10%) 0%,
hsl(200 80% 33%) 15% 15%, 30%,
hsl(36 90% 50%) 50%, 70%,
hsl(200 80% 33%) 85% 85%,
hsl(240 50% 10%) 100%
)`,
backgroundPositionY: `${gradientOffset}px`,
backgroundRepeat: `repeat-y`
}}
>
{[...Array(24)].map((_, i) => {
const adjustedHour =
(tz.hour - hoursBeforeCurrent + i + 24) % 24;
// const hour12 = adjustedHour % 12 || 12;
// const ampm = adjustedHour < 12 ? "AM" : "PM";
let type = "dayNight";
if (adjustedHour >= 1 && adjustedHour <= 5)
type = "earlyMorning";
else if (adjustedHour >= 6 && adjustedHour <= 7)
type = "morning";
else if (adjustedHour >= 19 && adjustedHour <= 24)
type = "evening";
if (adjustedHour === 0) {
return (
<HourBox
key={i}
content={`${tz.month.toUpperCase()}\n${tz.day}`}
type="date"
isCurrentHour={false}
/>
);
}
return (
<HourBox
key={i}
content={`${adjustedHour}`}
type={type}
isCurrentHour={i === hoursBeforeCurrent}
/>
);
})}
</div>
</div>
<HourBox content={`${tz.name}`} type="tzName"></HourBox>
</div>
);
})}
<div
className={currentHourConnector}
style={{ top: `${ ( ( hoursBeforeCurrent + 24 ) * 36) + 2}px`, width: `${timezones_count * 49}px` }}
/>
</div>
</div>
</div>
);
};
const container = css`
:hover {
opacity: 1;
}
opacity: 1;
font-family: system-ui;
position: fixed;
width: fit-content;
height: fit-content;
// border-width: 1px 0 1px 1px;
// border-style: dotted;
// border-color: rgb(255 255 255 / 0.1);
// border-radius: 1rem 0 0 1rem;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 1rem;
top: -60px;
right: 40px;
padding: 1rem 2rem;
background-color: rgba(0, 0, 0, 0.2);
overflow: hidden;
box-shadow: -5px 5px 10px rgb(0 0 0 / .3);
transform: perspective(1500px) rotateX(40deg);
`;
const widgetContent = css`
display: flex;
justify-content: flex-start;
position: relative;
z-index: 1;
`;
const timezoneName = css`
color: hsl(0 0 100 / .5);
font-size: 16px;
font-weight: 300;
`;
const rowsWrapper = css`
display: flex;
flex-direction: row-reverse;
gap: 12px;
`;
const timezoneRow = css`
`;
const hoursContainerWrapper = css`
overflow: hidden;
// border: 1px solid rgba(255, 255, 255, 0.2);
`;
const hoursContainer = css`
display: flex;
flex-direction: column-reverse;
border-radius: 10px;
`;
const currentTimezone = css`
// border: 1px solid hsl(0 100 100 / 0.6);
`;
const otherTimezone = css`
opacity: 0.7;
`;
const hourBox = css`
width: 36px;
height: 36px;
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
flex-shrink: 0;
flex-direction: column;
line-height: 1;
`;
const earlyMorning = css`
// background-color: rgba(51, 51, 51, 0.1);
`;
const morning = css`
// background-color: rgba(102, 102, 102, 0.1);
`;
const dayNight = css`
// background-color: rgba(255, 255, 255, 0.1);
`;
const dateBox = css`
// background-color: rgba(51, 51, 51, 0.1);
width: 36px;
white-space: pre-line;
line-height: 1;
font-size: 11px !important;
text-align: center;
`;
const currentHour = css`
font-size: 18px;
font-weight: bold;
z-index: 4;
`;
const currentHourConnector = css`
position: absolute;
right: -10px;
border: 1px solid hsl(0 100 100 / 0.5);
border-radius: 5px;
height: 36px;
z-index: 10;
display:none;
`;
@BorisAnthony
Copy link
Author

Screenshot 2024-10-09 at 10 00 36

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment