Days Left This Year

Days Left This Year

Layout Variations

See how this plugin adapts across different mashup views. Each view shows a single instance to demonstrate how the layout responds to available space.

Full View

value Days Passed
value Days Left
Days Left This Year 2026
<div class="layout layout--col gap--large">
  <div class="grid grid--cols-10">
    <div class="col col--span-1" />
    <div class="col col--span-4">
      <div class="item">
        <div class="meta" />
        <div class="content text--center">
          <span class="value value--xxxlarge days_passed" data-value-fit="true">value</span>
          <span class="label">Days Passed</span>
        </div>
      </div>
    </div>
    <div class="col col--span-4">
      <div class="item">
        <div class="meta" />
        <div class="content text--center">
          <span class="value value--xxxlarge days_left" data-value-fit="true">value</span>
          <span class="label">Days Left</span>
        </div>
      </div>
    </div>
    <div class="col col--span-1" />
  </div>
  <div class="w--full">
    <div id="days_left" data-today="2025-09-15T10:29:35+05:30" />
  </div>
</div>
<div class="title_bar">
  <img class="image" alt="" src="https://usetrmnl.com/images/plugins/days_left_year--render.svg" />
  <span class="title">Days Left This Year</span>
  <span class="instance">2026</span>
</div>

Half Horizontal

value Days Passed
value Days Left
Days Left This Year 2026
<div class="layout">
  <div class="flex flex--col gap--large" style="width: 200px">
    <div class="item">
      <div class="meta" />
      <div class="content">
        <span class="value days_passed">value</span>
        <span class="label">Days Passed</span>
      </div>
    </div>
    <div class="item">
      <div class="meta" />
      <div class="content">
        <span class="value days_left">value</span>
        <span class="label">Days Left</span>
      </div>
    </div>
  </div>
  <div class="grid grid--cols-2">
    <div class="w--full">
      <div id="days_left" data-today="2025-09-15T10:29:35+05:30" />
    </div>
  </div>
</div>
<div class="title_bar">
  <img class="image" alt="" src="https://usetrmnl.com/images/plugins/days_left_year--render.svg" />
  <span class="title">Days Left This Year</span>
  <span class="instance">2026</span>
</div>

Half Vertical

value Days Passed
value Days Left
Days Left This Year 2026
<div class="layout layout--col gap--large">
  <div class="grid grid--cols-2">
    <div class="item">
      <div class="meta" />
      <div class="content">
        <span class="value value--small days_passed">value</span>
        <span class="label">Days Passed</span>
      </div>
    </div>
    <div class="item">
      <div class="meta" />
      <div class="content">
        <span class="value value--small days_left">value</span>
        <span class="label">Days Left</span>
      </div>
    </div>
  </div>
  <div class="w--full">
    <div id="days_left" data-today="2025-09-15T10:29:35+05:30" />
  </div>
</div>
<div class="title_bar">
  <img class="image" alt="" src="https://usetrmnl.com/images/plugins/days_left_year--render.svg" />
  <span class="title">Days Left This Year</span>
  <span class="instance">2026</span>
</div>

Quadrant

value Days Passed
value Days Left
Days Left This Year 2026
<div class="layout layout--col gap--large">
  <div class="grid grid--cols-2">
    <div class="item">
      <div class="meta" />
      <div class="content">
        <span class="value value--small days_passed">value</span>
        <span class="label">Days Passed</span>
      </div>
    </div>
    <div class="item">
      <div class="meta" />
      <div class="content">
        <span class="value value--small days_left">value</span>
        <span class="label">Days Left</span>
      </div>
    </div>
  </div>
  <div class="w--full">
    <div id="days_left" data-today="2025-09-15T10:29:35+05:30" />
  </div>
</div>
<div class="title_bar">
  <img class="image" alt="" src="https://usetrmnl.com/images/plugins/days_left_year--render.svg" />
  <span class="title">Days Left This Year</span>
  <span class="instance">2026</span>
</div>

Shared

This plugin uses a shared file that contains shared CSS styles and/or JavaScript logic used across all layout variations.

#days_left {
        width: 689px;
        height: 147px;
        overflow: hidden;

        margin-left: 34px;

        column-count: auto;
        column-fill: auto;
        column-width: 13px;
        column-gap: 0px;
    }

    #days_left .day {
        width: 11px;
        height: 19px;
        float: left;
        border-radius: 4px;
        margin: 0px 0px 2px 0px;

        break-inside: avoid-column;
    }

    .view--quadrant #days_left {
        width: 318px;
        height: 70px;
        column-width: 6px;
        margin-top: 0;
        padding-left: 0;
        margin-left: 0px;
    }

    .view--quadrant #days_left .day {
        width: 5px;
        height: 9px;
        border-radius: 2px;
        margin: 0 0 1px 0;
    }

    .view--half_vertical #days_left {
        width: 318px;
        height: 315px;
        column-width: 6px;
        margin-top: 0;
        padding-left: 0;
        margin-left: 0px;
    }

    .view--half_vertical #days_left .day {
        width: 5px;
        height: 43px;
        margin: 0 0 2px 0px;
    }

    .view--half_horizontal #days_left {
        width: 583px;
        height: 147px;
        column-width: 11px;
        margin-top: 0;
        padding-left: 0;
        margin-left: 0;
        margin-right: 7px;
    }

    .view--half_horizontal #days_left .day {
        width: 9px;
        height: 19px;
    }
document.addEventListener('DOMContentLoaded', () => {
    const yearContainers = document.querySelectorAll('#days_left');
    const today = yearContainers[0].dataset['today'];
    const now = new Date(today);

    // Get the offset for the first day of the year (e.g. start of week is Mon and Jan 1 is Wed -> 2 days)
    let firstDayOfWeek = 1; // 0=Sunday, 1=Monday, etc.

    function createYearDivs(container) {
      container.innerHTML = ''; // Clear the container before adding new divs
      const totalDays = getDaysInYear(now.getFullYear());
      const dayOffset = getDayOffset(firstDayOfWeek);

      // Add empty divs for pre-January 1st days of first week
      for (let i = 0; i < dayOffset; i++) {
        const dayDiv = document.createElement('div');
        dayDiv.classList.add('day', 'offset', 'bg-white');
        container.appendChild(dayDiv);
      }

      // Add actual days
      for (let i = 0; i < totalDays; i++) {
        const dayDiv = document.createElement('div');
        dayDiv.classList.add('day');
        container.appendChild(dayDiv);
      }
    }

    function updatePassedDays(container) {
      const daysPassed = getYearProgress(now);
      const dayDivs = Array.from(container.getElementsByClassName('day'))
        .filter(day => !day.classList.contains('offset'));

      // Highlight passed days
      for (let i = 0; i < daysPassed; i++) {
        dayDivs[i].classList.add('passed', 'bg--gray-4', '2bit:bg--gray-50');
      }

      for (let i = daysPassed; i < dayDivs.length; i++) {
        dayDivs[i].classList.add('today', 'bg--gray-5', '2bit:bg--gray-65');
      }

      // Highlight the current day
      if (dayDivs[daysPassed]) {
        dayDivs[daysPassed].classList.remove('bg--gray-5', '2bit:bg--gray-65');
        dayDivs[daysPassed].classList.add('bg-black');
      }

      // Update metric values
      const daysPassedElements = document.querySelectorAll('.days_passed');
      const daysLeftElements = document.querySelectorAll('.days_left');

      daysPassedElements.forEach(element => {
        element.textContent = daysPassed;
      });

      daysLeftElements.forEach(element => {
        element.textContent = dayDivs.length - daysPassed;
      });
    }

    function getDaysInYear(year) {
      return isLeapYear(year) ? 366 : 365;
    }

    function isLeapYear(year) {
      return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0);
    }

    function getFirstDay() {
      return new Date(now.getFullYear(), 0, 1).getDay(); // what day of the week is Jan 1st
    }

    function getDayOffset() {
      return (getFirstDay() - firstDayOfWeek + 7) % 7; // Offset based on preference
    }

    function getYearProgress(date) {
      const startOfYear = new Date(date.getFullYear(), 0, 1);
      const startOffset = startOfYear.getTimezoneOffset();
      const currentOffset = date.getTimezoneOffset();
      const offsetDifference = (startOffset - currentOffset) * 60 * 1000;
      const diff = (date - startOfYear) + offsetDifference;
      const oneDay = 1000 * 60 * 60 * 24;
      return Math.floor(diff / oneDay);
    }

    yearContainers.forEach(container => {
      createYearDivs(container);
      updatePassedDays(container);
    });
  });