calendar

Calendar date grid structure

Use data-calendar-generated with data-month="YYYY-MM" to render a complete month, including outside days. Previous and next controls update the visible month, while selecting a date updates data-value and emits angularcss:calendar-select. Bind that event with AngularTS ng-on-* so application state remains responsible for the selected value.

<section
  ng-calendar
  data-calendar-generated
  data-month="2026-05"
  data-value="{{ selectedDate }}"
  ng-on-angularcss:calendar-select="selectedDate = $event.detail.value"
>
  <header>
    <button type="button">Previous</button>
    <h2></h2>
    <button type="button">Next</button>
  </header>
  <div></div>
</section>

Use data-week-start="0" through "6" to choose the first weekday and data-show-outside-days="false" to hide outside dates. Set --calendar-cell-size in CSS to resize cells. Day cells support arrow keys, Home, End, Page Up, and Page Down. Month changes emit angularcss:calendar-month-change.

Omit data-calendar-generated to author every weekday and day cell yourself. This mode supports selected, today, outside-month, disabled, booked, range, and week-number attributes without replacing application markup.

Date pickers are compositions rather than a second model implementation: use a native date or text input with ng-model, a field and label, a popover, and this calendar grid. Use native input[type="time"] for time values and ordinary buttons for presets. Booked dates use disabled plus data-booked="true"; custom day content can be nested inside a date button, and generated week numbers use native data elements.

The generated calendar is a Gregorian local-date UI backed by date-fns. Non-Gregorian engines, natural-language parsing, and IANA time-zone conversion are explicit application adapters: they provide localized labels and stable YYYY-MM-DD values to the calendar, or bind native inputs and zone selectors with AngularTS ng-model. AngularCSS does not silently convert calendar systems or instants because those conversions require application locale and time-zone policy.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Calendar</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="selectedDate='2026-05-14'"
    data-example="calendar-demo"
  >
    <div class="stack-sm">
      <section
        ng-calendar
        data-calendar-generated
        data-month="2026-05"
        data-value="{{ selectedDate }}"
        data-caption-layout="dropdown"
        data-start-year="2024"
        data-end-year="2028"
        ng-on-angularcss:calendar-select="selectedDate = $event.detail.value"
        class="calendar-demo visual-example"
      >
        <header>
          <button
            type="button"
            size="icon"
            variant="ghost"
            aria-label="Previous month"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="m15 18-6-6 6-6" />
            </svg>
          </button>
          <h3></h3>
          <button
            type="button"
            size="icon"
            variant="ghost"
            aria-label="Next month"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="m9 18 6-6-6-6" />
            </svg>
          </button>
        </header>
        <div></div>
      </section>
      <output class="output" aria-live="polite">
        Selected: {{ selectedDate }}
      </output>
    </div>
  </body>
</html>

Selection And Options

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Calendar Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="calendar={basic:'',booked:'2026-09-08',caption:'2026-09-12',multiple:'2026-09-10,2026-09-12',rangeStart:'2026-09-10',rangeEnd:'2026-09-15',week:'2026-09-12'}"
    data-example="calendar-basic calendar-booked-dates calendar-caption calendar-multiple calendar-range calendar-week-numbers"
  >
    <main
      class="calendar-workflow-grid"
      aria-label="Calendar selection workflows"
    >
      <section
        class="calendar-workflow"
        aria-labelledby="calendar-basic-heading"
      >
        <h2 id="calendar-basic-heading">Basic</h2>
        <section
          ng-calendar
          data-calendar-generated
          data-month="2026-09"
          data-value="{{ calendar.basic }}"
          ng-on-angularcss:calendar-select="calendar.basic=$event.detail.value"
          class="calendar-demo"
        >
          <header>
            <button
              type="button"
              size="icon"
              variant="ghost"
              aria-label="Previous basic month"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <path d="m15 18-6-6 6-6" />
              </svg>
            </button>
            <h3></h3>
            <button
              type="button"
              size="icon"
              variant="ghost"
              aria-label="Next basic month"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <path d="m9 18 6-6-6-6" />
              </svg>
            </button>
          </header>
          <div></div>
        </section>
        <output class="calendar-workflow-output" aria-live="polite">
          Selected: {{ calendar.basic || 'None' }}
        </output>
      </section>

      <section
        class="calendar-workflow"
        aria-labelledby="calendar-booked-heading"
      >
        <h2 id="calendar-booked-heading">Booked dates</h2>
        <article class="calendar-card card">
          <section class="calendar-card-content">
            <section
              ng-calendar
              data-calendar-generated
              data-month="2026-09"
              data-value="{{ calendar.booked }}"
              data-booked-dates="2026-09-10,2026-09-11,2026-09-12,2026-09-13,2026-09-14,2026-09-15,2026-09-16,2026-09-17,2026-09-18,2026-09-19,2026-09-20,2026-09-21,2026-09-22,2026-09-23,2026-09-24"
              ng-on-angularcss:calendar-select="calendar.booked=$event.detail.value"
            >
              <header>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Previous availability month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m15 18-6-6 6-6" />
                  </svg>
                </button>
                <h3></h3>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Next availability month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m9 18 6-6-6-6" />
                  </svg>
                </button>
              </header>
              <div></div>
            </section>
          </section>
        </article>
        <output class="calendar-workflow-output" aria-live="polite">
          Available date: {{ calendar.booked }}
        </output>
      </section>

      <section
        class="calendar-workflow"
        aria-labelledby="calendar-caption-heading"
      >
        <h2 id="calendar-caption-heading">Dropdown caption</h2>
        <section
          ng-calendar
          data-calendar-generated
          data-month="2026-09"
          data-value="{{ calendar.caption }}"
          data-caption-layout="dropdown"
          data-start-year="2024"
          data-end-year="2028"
          ng-on-angularcss:calendar-select="calendar.caption=$event.detail.value"
          class="calendar-demo"
        >
          <header>
            <button
              type="button"
              size="icon"
              variant="ghost"
              aria-label="Previous caption month"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <path d="m15 18-6-6 6-6" />
              </svg>
            </button>
            <h3></h3>
            <button
              type="button"
              size="icon"
              variant="ghost"
              aria-label="Next caption month"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <path d="m9 18 6-6-6-6" />
              </svg>
            </button>
          </header>
          <div></div>
        </section>
        <output class="calendar-workflow-output" aria-live="polite">
          Selected: {{ calendar.caption }}
        </output>
      </section>

      <section
        class="calendar-workflow"
        aria-labelledby="calendar-multiple-heading"
      >
        <h2 id="calendar-multiple-heading">Multiple dates</h2>
        <article class="calendar-card card">
          <section class="calendar-card-content">
            <section
              ng-calendar
              data-calendar-generated
              data-month="2026-09"
              data-selection-mode="multiple"
              data-values="{{ calendar.multiple }}"
              ng-on-angularcss:calendar-select="calendar.multiple=$event.detail.values"
            >
              <header>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Previous multiple month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m15 18-6-6 6-6" />
                  </svg>
                </button>
                <h3></h3>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Next multiple month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m9 18 6-6-6-6" />
                  </svg>
                </button>
              </header>
              <div></div>
            </section>
          </section>
        </article>
        <output class="calendar-workflow-output" aria-live="polite">
          Selected dates: {{ calendar.multiple || 'None' }}
        </output>
      </section>

      <section
        class="calendar-workflow calendar-workflow-wide"
        aria-labelledby="calendar-range-heading"
      >
        <h2 id="calendar-range-heading">Date range</h2>
        <section
          ng-calendar
          data-calendar-generated
          data-month="2026-09"
          data-number-of-months="2"
          data-selection-mode="range"
          data-range-start-value="{{ calendar.rangeStart }}"
          data-range-end-value="{{ calendar.rangeEnd }}"
          ng-on-angularcss:calendar-select="calendar.rangeStart=$event.detail.range.start; calendar.rangeEnd=$event.detail.range.end"
          class="calendar-demo"
        >
          <header>
            <button
              type="button"
              size="icon"
              variant="ghost"
              aria-label="Previous range month"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <path d="m15 18-6-6 6-6" />
              </svg>
            </button>
            <h3></h3>
            <button
              type="button"
              size="icon"
              variant="ghost"
              aria-label="Next range month"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <path d="m9 18 6-6-6-6" />
              </svg>
            </button>
          </header>
          <div></div>
        </section>
        <output class="calendar-workflow-output" aria-live="polite">
          Range: {{ calendar.rangeStart || 'None' }} to {{ calendar.rangeEnd ||
          'None' }}
        </output>
      </section>

      <section
        class="calendar-workflow"
        aria-labelledby="calendar-week-heading"
      >
        <h2 id="calendar-week-heading">Week numbers</h2>
        <article class="calendar-card card">
          <section class="calendar-card-content">
            <section
              ng-calendar
              data-calendar-generated
              data-month="2026-09"
              data-value="{{ calendar.week }}"
              data-show-week-numbers="true"
              ng-on-angularcss:calendar-select="calendar.week=$event.detail.value"
            >
              <header>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Previous week-number month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m15 18-6-6 6-6" />
                  </svg>
                </button>
                <h3></h3>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Next week-number month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m9 18 6-6-6-6" />
                  </svg>
                </button>
              </header>
              <div></div>
            </section>
          </section>
        </article>
        <output class="calendar-workflow-output" aria-live="polite">
          Selected: {{ calendar.week }}
        </output>
      </section>
    </main>
  </body>
</html>

Reference Compositions

Custom day content remains authored HTML, while presets and time values use ordinary buttons and native inputs bound by AngularTS. The Persian example is an explicit application-provided calendar-system adapter: it supplies localized labels and stable Gregorian interchange values without adding a second calendar engine to AngularCSS.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Calendar Compositions</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="custom={start:'2026-09-10',end:'2026-09-15'}; presetDate='2026-09-12'; time={date:'2026-09-12',start:'09:00',end:'17:00'}; rtlDate='2026-09-12'; hijriDate='2025-06-12'; customDays=[{v:'2026-08-30',d:'30',p:'',o:true},{v:'2026-08-31',d:'31',p:'',o:true},{v:'2026-09-01',d:'1',p:'$100',o:false},{v:'2026-09-02',d:'2',p:'$100',o:false},{v:'2026-09-03',d:'3',p:'$100',o:false},{v:'2026-09-04',d:'4',p:'$100',o:false},{v:'2026-09-05',d:'5',p:'$120',o:false},{v:'2026-09-06',d:'6',p:'$120',o:false},{v:'2026-09-07',d:'7',p:'$100',o:false},{v:'2026-09-08',d:'8',p:'$100',o:false},{v:'2026-09-09',d:'9',p:'$100',o:false},{v:'2026-09-10',d:'10',p:'$100',o:false},{v:'2026-09-11',d:'11',p:'$100',o:false},{v:'2026-09-12',d:'12',p:'$120',o:false},{v:'2026-09-13',d:'13',p:'$120',o:false},{v:'2026-09-14',d:'14',p:'$100',o:false},{v:'2026-09-15',d:'15',p:'$100',o:false},{v:'2026-09-16',d:'16',p:'$100',o:false},{v:'2026-09-17',d:'17',p:'$100',o:false},{v:'2026-09-18',d:'18',p:'$100',o:false},{v:'2026-09-19',d:'19',p:'$120',o:false},{v:'2026-09-20',d:'20',p:'$120',o:false},{v:'2026-09-21',d:'21',p:'$100',o:false},{v:'2026-09-22',d:'22',p:'$100',o:false},{v:'2026-09-23',d:'23',p:'$100',o:false},{v:'2026-09-24',d:'24',p:'$100',o:false},{v:'2026-09-25',d:'25',p:'$100',o:false},{v:'2026-09-26',d:'26',p:'$120',o:false},{v:'2026-09-27',d:'27',p:'$120',o:false},{v:'2026-09-28',d:'28',p:'$100',o:false},{v:'2026-09-29',d:'29',p:'$100',o:false},{v:'2026-09-30',d:'30',p:'$100',o:false},{v:'2026-10-01',d:'1',p:'',o:true},{v:'2026-10-02',d:'2',p:'',o:true},{v:'2026-10-03',d:'3',p:'',o:true},{v:'2026-10-04',d:'4',p:'',o:true},{v:'2026-10-05',d:'5',p:'',o:true},{v:'2026-10-06',d:'6',p:'',o:true},{v:'2026-10-07',d:'7',p:'',o:true},{v:'2026-10-08',d:'8',p:'',o:true},{v:'2026-10-09',d:'9',p:'',o:true},{v:'2026-10-10',d:'10',p:'',o:true}]; hijriDays=[{v:'2025-05-17',d:'۲۷',o:true},{v:'2025-05-18',d:'۲۸',o:true},{v:'2025-05-19',d:'۲۹',o:true},{v:'2025-05-20',d:'۳۰',o:true},{v:'2025-05-21',d:'۳۱',o:true},{v:'2025-05-22',d:'۱',o:false},{v:'2025-05-23',d:'۲',o:false},{v:'2025-05-24',d:'۳',o:false},{v:'2025-05-25',d:'۴',o:false},{v:'2025-05-26',d:'۵',o:false},{v:'2025-05-27',d:'۶',o:false},{v:'2025-05-28',d:'۷',o:false},{v:'2025-05-29',d:'۸',o:false},{v:'2025-05-30',d:'۹',o:false},{v:'2025-05-31',d:'۱۰',o:false},{v:'2025-06-01',d:'۱۱',o:false},{v:'2025-06-02',d:'۱۲',o:false},{v:'2025-06-03',d:'۱۳',o:false},{v:'2025-06-04',d:'۱۴',o:false},{v:'2025-06-05',d:'۱۵',o:false},{v:'2025-06-06',d:'۱۶',o:false},{v:'2025-06-07',d:'۱۷',o:false},{v:'2025-06-08',d:'۱۸',o:false},{v:'2025-06-09',d:'۱۹',o:false},{v:'2025-06-10',d:'۲۰',o:false},{v:'2025-06-11',d:'۲۱',o:false},{v:'2025-06-12',d:'۲۲',o:false},{v:'2025-06-13',d:'۲۳',o:false},{v:'2025-06-14',d:'۲۴',o:false},{v:'2025-06-15',d:'۲۵',o:false},{v:'2025-06-16',d:'۲۶',o:false},{v:'2025-06-17',d:'۲۷',o:false},{v:'2025-06-18',d:'۲۸',o:false},{v:'2025-06-19',d:'۲۹',o:false},{v:'2025-06-20',d:'۳۰',o:false},{v:'2025-06-21',d:'۳۱',o:false},{v:'2025-06-22',d:'۱',o:true},{v:'2025-06-23',d:'۲',o:true},{v:'2025-06-24',d:'۳',o:true},{v:'2025-06-25',d:'۴',o:true},{v:'2025-06-26',d:'۵',o:true},{v:'2025-06-27',d:'۶',o:true}]"
    data-example="calendar-custom-days calendar-presets calendar-rtl calendar-time calendar-hijri"
  >
    <main class="calendar-composition-grid" aria-label="Calendar compositions">
      <section
        class="calendar-composition calendar-composition-wide"
        aria-labelledby="custom-days-heading"
      >
        <h2 id="custom-days-heading">Custom day prices</h2>
        <article class="calendar-card card">
          <section class="calendar-card-content">
            <section
              ng-calendar
              data-selection-mode="range"
              data-range-start-value="{{ custom.start }}"
              data-range-end-value="{{ custom.end }}"
              ng-on-angularcss:calendar-select="custom.start=$event.detail.range.start; custom.end=$event.detail.range.end"
              class="calendar-custom-days"
            >
              <header>
                <h3>September 2026</h3>
              </header>
              <div>
                <abbr>Su</abbr><abbr>Mo</abbr><abbr>Tu</abbr><abbr>We</abbr
                ><abbr>Th</abbr><abbr>Fr</abbr><abbr>Sa</abbr>
                <button
                  type="button"
                  ng-repeat="day in customDays"
                  value="{{ day.v }}"
                  data-outside="{{ day.o }}"
                  aria-label="{{ day.v }} {{ day.p }}"
                >
                  <strong>{{ day.d }}</strong><span>{{ day.p }}</span>
                </button>
              </div>
            </section>
          </section>
        </article>
        <output class="calendar-workflow-output" aria-live="polite">
          Range: {{ custom.start }} to {{ custom.end }}
        </output>
      </section>

      <section class="calendar-composition" aria-labelledby="preset-heading">
        <h2 id="preset-heading">Presets</h2>
        <article size="sm" class="calendar-preset-card card">
          <section class="calendar-preset-content">
            <section
              ng-calendar
              data-calendar-generated
              data-month="2026-09"
              data-value="{{ presetDate }}"
              ng-on-angularcss:calendar-select="presetDate=$event.detail.value"
              class="calendar-flush calendar-preset-grid"
            >
              <header>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Previous preset month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m15 18-6-6 6-6" />
                  </svg>
                </button>
                <h3></h3>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Next preset month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m9 18 6-6-6-6" />
                  </svg>
                </button>
              </header>
              <div></div>
            </section>
          </section>
          <footer class="calendar-preset-footer">
            <button
              type="button"
              variant="outline"
              size="sm"
              ng-click="presetDate='2026-09-12'"
            >
              Today
            </button>
            <button
              type="button"
              variant="outline"
              size="sm"
              ng-click="presetDate='2026-09-13'"
            >
              Tomorrow
            </button>
            <button
              type="button"
              variant="outline"
              size="sm"
              ng-click="presetDate='2026-09-15'"
            >
              In 3 days
            </button>
            <button
              type="button"
              variant="outline"
              size="sm"
              ng-click="presetDate='2026-09-19'"
            >
              In a week
            </button>
            <button
              type="button"
              variant="outline"
              size="sm"
              ng-click="presetDate='2026-09-26'"
            >
              In 2 weeks
            </button>
          </footer>
        </article>
        <output class="calendar-workflow-output" aria-live="polite">
          Selected: {{ presetDate }}
        </output>
      </section>

      <section class="calendar-composition" aria-labelledby="time-heading">
        <h2 id="time-heading">Date and time</h2>
        <article size="sm" class="calendar-time-card card">
          <section class="calendar-time-content">
            <section
              ng-calendar
              data-calendar-generated
              data-month="2026-09"
              data-value="{{ time.date }}"
              ng-on-angularcss:calendar-select="time.date=$event.detail.value"
              class="calendar-flush"
            >
              <header>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Previous time month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m15 18-6-6 6-6" />
                  </svg>
                </button>
                <h3></h3>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Next time month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m9 18 6-6-6-6" />
                  </svg>
                </button>
              </header>
              <div></div>
            </section>
          </section>
          <footer class="calendar-time-footer">
            <label
              ><span>Start</span>
              <div class="input-group">
                <input
                  type="time"
                  ng-model="time.start"
                  aria-label="Start time"
                /><span
                  ><svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <circle cx="12" cy="12" r="9" />
                    <path d="M12 7v5l3 2" /></svg
                ></span></div
            ></label>
            <label
              ><span>End</span>
              <div class="input-group">
                <input
                  type="time"
                  ng-model="time.end"
                  aria-label="End time"
                /><span
                  ><svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <circle cx="12" cy="12" r="9" />
                    <path d="M12 7v5l3 2" /></svg
                ></span></div
            ></label>
          </footer>
        </article>
        <output class="calendar-workflow-output" aria-live="polite">
          {{ time.date }} · {{ time.start }}–{{ time.end }}
        </output>
      </section>

      <section
        class="calendar-composition"
        aria-labelledby="rtl-heading"
        dir="rtl"
        lang="ar-SA"
      >
        <h2 id="rtl-heading">تقويم من اليمين إلى اليسار</h2>
        <section
          ng-calendar
          data-calendar-generated
          data-month="2026-09"
          data-value="{{ rtlDate }}"
          data-caption-layout="dropdown"
          data-start-year="2024"
          data-end-year="2028"
          ng-on-angularcss:calendar-select="rtlDate=$event.detail.value"
          class="calendar-demo calendar-rtl-grid"
        >
          <header>
            <button
              type="button"
              size="icon"
              variant="ghost"
              aria-label="الشهر السابق"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <path d="m15 18-6-6 6-6" />
              </svg>
            </button>
            <h3></h3>
            <button
              type="button"
              size="icon"
              variant="ghost"
              aria-label="الشهر التالي"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <path d="m9 18 6-6-6-6" />
              </svg>
            </button>
          </header>
          <div></div>
        </section>
        <output class="calendar-workflow-output" aria-live="polite">
          التاريخ: {{ rtlDate }}
        </output>
      </section>

      <section
        class="calendar-composition"
        aria-labelledby="hijri-heading"
        dir="rtl"
        lang="fa"
      >
        <h2 id="hijri-heading">تقویم هجری شمسی</h2>
        <section
          ng-calendar
          data-value="{{ hijriDate }}"
          ng-on-angularcss:calendar-select="hijriDate=$event.detail.value"
          class="calendar-demo calendar-hijri-grid"
          aria-label="خرداد ۱۴۰۴"
        >
          <header>
            <h3>خرداد ۱۴۰۴</h3>
          </header>
          <div>
            <abbr>ش</abbr><abbr>ی</abbr><abbr>د</abbr><abbr>س</abbr
            ><abbr>چ</abbr><abbr>پ</abbr><abbr>ج</abbr>
            <button
              type="button"
              ng-repeat="day in hijriDays"
              value="{{ day.v }}"
              data-outside="{{ day.o }}"
              aria-label="روز {{ day.d }}"
            >
              {{ day.d }}
            </button>
          </div>
        </section>
        <output class="calendar-workflow-output" aria-live="polite">
          روز انتخاب‌شده: {{ hijriDate }}
        </output>
      </section>
    </main>
  </body>
</html>

Date Picker Compositions

Date Picker is a composition of Field, Input Group, Popover, Calendar, Button, and native time input primitives. The artifact below implements all eight checked-in reference workflows: basic, standalone demo, date of birth, parsed text input, natural-language input, range, RTL, and date with time.

The page loads a locally bundled TypeScript application adapter. AngularTS owns the values and commands, while chrono-node parses natural-language input into the Calendar’s stable YYYY-MM-DD interchange value. No CDN or source TypeScript module is loaded by the example.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Date Picker Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
    <script src="../../js/date-picker-demo.umd.js"></script>
  </head>
  <body
    ng-app="datePickerDemo"
    ng-controller="DatePickerDemoController as picker"
    ng-cloak
    data-example="date-picker-basic date-picker-demo date-picker-dob date-picker-input date-picker-natural-language date-picker-range date-picker-rtl date-picker-time"
  >
    <main class="date-picker-grid" aria-label="Date picker workflows">
      <section class="date-picker-workflow">
        <h2>Basic</h2>
        <div class="date-picker-field-compact field">
          <label for="date-picker-basic">Date</label>
          <span id="date-picker-basic-popover">
            <button
              id="date-picker-basic"
              type="button"
              variant="outline"
              class="date-picker-trigger"
              popovertarget="popover-date-picker-workflows-1-content"
            >
              {{ picker.basicDate ? picker.format(picker.basicDate) : 'Pick a
              date' }}
            </button>
            <aside
              class="calendar-popover-content"
              aria-label="Choose a basic date"
              id="popover-date-picker-workflows-1-content"
              side="bottom"
              align="start"
              popover
            >
              <section
                ng-calendar
                data-calendar-generated
                data-month="2026-09"
                ng-attr-data-value="{{ picker.basicDate }}"
                ng-on-angularcss:calendar-select="picker.selectBasic($event.detail.value)"
              >
                <header>
                  <button
                    type="button"
                    size="icon"
                    variant="ghost"
                    aria-label="Previous basic month"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <path d="m15 18-6-6 6-6"></path>
                    </svg>
                  </button>
                  <h3></h3>
                  <button
                    type="button"
                    size="icon"
                    variant="ghost"
                    aria-label="Next basic month"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <path d="m9 18 6-6-6-6"></path>
                    </svg>
                  </button>
                </header>
                <div></div>
              </section>
            </aside>
          </span>
        </div>
      </section>

      <section class="date-picker-workflow">
        <h2>Demo</h2>
        <span id="date-picker-demo-popover">
          <button
            type="button"
            variant="outline"
            class="date-picker-trigger date-picker-trigger-between"
            ng-attr-empty="{{ picker.demoDate ? undefined : '' }}"
            popovertarget="popover-date-picker-workflows-2-content"
          >
            <span
              >{{ picker.demoDate ? picker.format(picker.demoDate) : 'Pick a
              date' }}</span
            >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="m6 9 6 6 6-6"></path>
            </svg>
          </button>
          <aside
            class="calendar-popover-content"
            aria-label="Choose a demo date"
            id="popover-date-picker-workflows-2-content"
            side="bottom"
            align="start"
            popover
          >
            <section
              ng-calendar
              data-calendar-generated
              data-month="2026-09"
              ng-attr-data-value="{{ picker.demoDate }}"
              ng-on-angularcss:calendar-select="picker.selectDemo($event.detail.value)"
            >
              <header>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Previous demo month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m15 18-6-6 6-6"></path>
                  </svg>
                </button>
                <h3></h3>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Next demo month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m9 18 6-6-6-6"></path>
                  </svg>
                </button>
              </header>
              <div></div>
            </section>
          </aside>
        </span>
      </section>

      <section class="date-picker-workflow">
        <h2>Date of birth</h2>
        <div class="date-picker-field-compact field">
          <label for="date-picker-dob">Date of birth</label>
          <span id="date-picker-dob-popover">
            <button
              id="date-picker-dob"
              type="button"
              variant="outline"
              class="date-picker-trigger"
              popovertarget="popover-date-picker-workflows-3-content"
            >
              {{ picker.dobDate ? picker.format(picker.dobDate) : 'Select date'
              }}
            </button>
            <aside
              class="calendar-popover-content"
              aria-label="Choose a birth date"
              id="popover-date-picker-workflows-3-content"
              side="bottom"
              align="start"
              popover
            >
              <section
                ng-calendar
                data-calendar-generated
                ng-attr-data-month="{{ picker.month(picker.dobDate) }}"
                ng-attr-data-value="{{ picker.dobDate }}"
                data-caption-layout="dropdown"
                data-start-year="1900"
                data-end-year="2026"
                ng-on-angularcss:calendar-select="picker.selectDob($event.detail.value)"
              >
                <header>
                  <button
                    type="button"
                    size="icon"
                    variant="ghost"
                    aria-label="Previous birth month"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <path d="m15 18-6-6 6-6"></path>
                    </svg>
                  </button>
                  <h3></h3>
                  <button
                    type="button"
                    size="icon"
                    variant="ghost"
                    aria-label="Next birth month"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <path d="m9 18 6-6-6-6"></path>
                    </svg>
                  </button>
                </header>
                <div></div>
              </section>
            </aside>
          </span>
        </div>
      </section>

      <section class="date-picker-workflow">
        <h2>Input</h2>
        <div class="date-picker-input-field field">
          <label for="date-picker-input">Subscription Date</label>
          <div class="input-group">
            <input
              id="date-picker-input"
              ng-model="picker.inputValue"
              data-change="picker.updateInput()"
              ng-keydown="picker.openPopover('date-picker-input-popover', $event)"
              placeholder="June 01, 2025"
            />
            <div align="inline-end">
              <span id="date-picker-input-popover">
                <button
                  type="button"
                  variant="ghost"
                  size="icon-xs"
                  aria-label="Select subscription date"
                  popovertarget="popover-date-picker-workflows-4-content"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <rect x="3" y="5" width="18" height="16" rx="2"></rect>
                    <path d="M16 3v4M8 3v4M3 10h18"></path>
                  </svg>
                </button>
                <aside
                  class="calendar-popover-content"
                  aria-label="Choose a subscription date"
                  id="popover-date-picker-workflows-4-content"
                  side="bottom"
                  align="end"
                  popover
                >
                  <section
                    ng-calendar
                    data-calendar-generated
                    ng-attr-data-month="{{ picker.month(picker.inputDate) }}"
                    ng-attr-data-value="{{ picker.inputDate }}"
                    ng-on-angularcss:calendar-select="picker.selectInput($event.detail.value)"
                  >
                    <header>
                      <button
                        type="button"
                        size="icon"
                        variant="ghost"
                        aria-label="Previous subscription month"
                      >
                        <svg
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          stroke-width="2"
                          aria-hidden="true"
                        >
                          <path d="m15 18-6-6 6-6"></path>
                        </svg>
                      </button>
                      <h3></h3>
                      <button
                        type="button"
                        size="icon"
                        variant="ghost"
                        aria-label="Next subscription month"
                      >
                        <svg
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          stroke-width="2"
                          aria-hidden="true"
                        >
                          <path d="m9 18 6-6-6-6"></path>
                        </svg>
                      </button>
                    </header>
                    <div></div>
                  </section>
                </aside>
              </span>
            </div>
          </div>
        </div>
      </section>

      <section class="date-picker-workflow date-picker-workflow-wide">
        <h2>Natural language</h2>
        <div class="date-picker-natural-field field">
          <label for="date-picker-natural">Schedule Date</label>
          <div class="input-group">
            <input
              id="date-picker-natural"
              ng-model="picker.naturalValue"
              data-change="picker.updateNatural()"
              ng-keydown="picker.openPopover('date-picker-natural-popover', $event)"
              placeholder="Tomorrow or next week"
            />
            <div align="inline-end">
              <span id="date-picker-natural-popover">
                <button
                  type="button"
                  variant="ghost"
                  size="icon-xs"
                  aria-label="Select schedule date"
                  popovertarget="popover-date-picker-workflows-5-content"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <rect x="3" y="5" width="18" height="16" rx="2"></rect>
                    <path d="M16 3v4M8 3v4M3 10h18"></path>
                  </svg>
                </button>
                <aside
                  class="calendar-popover-content"
                  aria-label="Choose a schedule date"
                  id="popover-date-picker-workflows-5-content"
                  side="bottom"
                  align="end"
                  popover
                >
                  <section
                    ng-calendar
                    data-calendar-generated
                    ng-attr-data-month="{{ picker.month(picker.naturalDate) }}"
                    ng-attr-data-value="{{ picker.naturalDate }}"
                    data-caption-layout="dropdown"
                    data-start-year="2024"
                    data-end-year="2028"
                    ng-on-angularcss:calendar-select="picker.selectNatural($event.detail.value)"
                  >
                    <header>
                      <button
                        type="button"
                        size="icon"
                        variant="ghost"
                        aria-label="Previous schedule month"
                      >
                        <svg
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          stroke-width="2"
                          aria-hidden="true"
                        >
                          <path d="m15 18-6-6 6-6"></path>
                        </svg>
                      </button>
                      <h3></h3>
                      <button
                        type="button"
                        size="icon"
                        variant="ghost"
                        aria-label="Next schedule month"
                      >
                        <svg
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          stroke-width="2"
                          aria-hidden="true"
                        >
                          <path d="m9 18 6-6-6-6"></path>
                        </svg>
                      </button>
                    </header>
                    <div></div>
                  </section>
                </aside>
              </span>
            </div>
          </div>
          <output class="calendar-workflow-output">
            Your post will be published on
            <strong>{{ picker.format(picker.naturalDate) }}</strong>.
          </output>
        </div>
      </section>

      <section class="date-picker-workflow date-picker-workflow-wide">
        <h2>Range</h2>
        <div class="date-picker-range-field field">
          <label for="date-picker-range">Date Picker Range</label>
          <span id="date-picker-range-popover">
            <button
              id="date-picker-range"
              type="button"
              variant="outline"
              class="date-picker-trigger"
              popovertarget="popover-date-picker-workflows-6-content"
            >
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                aria-hidden="true"
              >
                <rect x="3" y="5" width="18" height="16" rx="2"></rect>
                <path d="M16 3v4M8 3v4M3 10h18"></path>
              </svg>
              <span
                >{{ picker.formatShort(picker.rangeStart) }} - {{
                picker.formatShort(picker.rangeEnd) }}</span
              >
            </button>
            <aside
              class="calendar-popover-content"
              aria-label="Choose a date range"
              id="popover-date-picker-workflows-6-content"
              side="bottom"
              align="start"
              popover
            >
              <section
                ng-calendar
                data-calendar-generated
                ng-attr-data-month="{{ picker.month(picker.rangeStart) }}"
                data-number-of-months="2"
                data-selection-mode="range"
                ng-attr-data-range-start-value="{{ picker.rangeStart }}"
                ng-attr-data-range-end-value="{{ picker.rangeEnd }}"
                ng-on-angularcss:calendar-select="picker.selectRange($event.detail.range)"
              >
                <header>
                  <button
                    type="button"
                    size="icon"
                    variant="ghost"
                    aria-label="Previous range month"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <path d="m15 18-6-6 6-6"></path>
                    </svg>
                  </button>
                  <h3></h3>
                  <button
                    type="button"
                    size="icon"
                    variant="ghost"
                    aria-label="Next range month"
                  >
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      aria-hidden="true"
                    >
                      <path d="m9 18 6-6-6-6"></path>
                    </svg>
                  </button>
                </header>
                <div></div>
              </section>
            </aside>
          </span>
        </div>
      </section>

      <section class="date-picker-workflow" dir="rtl" lang="ar">
        <h2>من اليمين إلى اليسار</h2>
        <span id="date-picker-rtl-popover">
          <button
            type="button"
            variant="outline"
            class="date-picker-trigger date-picker-trigger-between"
            ng-attr-empty="{{ picker.rtlDate ? undefined : '' }}"
            popovertarget="popover-date-picker-workflows-7-content"
          >
            <span
              >{{ picker.rtlDate ? picker.formatRtl(picker.rtlDate) : 'اختر
              تاريخًا' }}</span
            >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="m6 9 6 6 6-6"></path>
            </svg>
          </button>
          <aside
            class="calendar-popover-content"
            aria-label="اختر تاريخًا"
            id="popover-date-picker-workflows-7-content"
            side="bottom"
            align="start"
            popover
          >
            <section
              ng-calendar
              data-calendar-generated
              data-month="2026-09"
              ng-attr-data-value="{{ picker.rtlDate }}"
              ng-on-angularcss:calendar-select="picker.selectRtl($event.detail.value)"
            >
              <header>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="الشهر السابق"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m15 18-6-6 6-6"></path>
                  </svg>
                </button>
                <h3></h3>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="الشهر التالي"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m9 18 6-6-6-6"></path>
                  </svg>
                </button>
              </header>
              <div></div>
            </section>
          </aside>
        </span>
      </section>

      <section class="date-picker-workflow date-picker-workflow-wide">
        <h2>Date and time</h2>
        <div class="date-picker-time-fields">
          <div class="field">
            <label for="date-picker-time-date">Date</label>
            <span id="date-picker-time-popover">
              <button
                id="date-picker-time-date"
                type="button"
                variant="outline"
                class="date-picker-trigger date-picker-trigger-between"
                popovertarget="popover-date-picker-workflows-8-content"
              >
                <span
                  >{{ picker.timeDate ? picker.formatShort(picker.timeDate) :
                  'Select date' }}</span
                >
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  aria-hidden="true"
                >
                  <path d="m6 9 6 6 6-6"></path>
                </svg>
              </button>
              <aside
                class="calendar-popover-content"
                aria-label="Choose an appointment date"
                id="popover-date-picker-workflows-8-content"
                side="bottom"
                align="start"
                popover
              >
                <section
                  ng-calendar
                  data-calendar-generated
                  ng-attr-data-month="{{ picker.month(picker.timeDate) }}"
                  ng-attr-data-value="{{ picker.timeDate }}"
                  data-caption-layout="dropdown"
                  data-start-year="2024"
                  data-end-year="2028"
                  ng-on-angularcss:calendar-select="picker.selectTimeDate($event.detail.value)"
                >
                  <header>
                    <button
                      type="button"
                      size="icon"
                      variant="ghost"
                      aria-label="Previous appointment month"
                    >
                      <svg
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        stroke-width="2"
                        aria-hidden="true"
                      >
                        <path d="m15 18-6-6 6-6"></path>
                      </svg>
                    </button>
                    <h3></h3>
                    <button
                      type="button"
                      size="icon"
                      variant="ghost"
                      aria-label="Next appointment month"
                    >
                      <svg
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        stroke-width="2"
                        aria-hidden="true"
                      >
                        <path d="m9 18 6-6-6-6"></path>
                      </svg>
                    </button>
                  </header>
                  <div></div>
                </section>
              </aside>
            </span>
          </div>
          <div class="field">
            <label for="date-picker-time-value">Time</label>
            <input
              id="date-picker-time-value"
              type="time"
              step="1"
              ng-model="picker.time"
            />
          </div>
        </div>
      </section>
    </main>
  </body>
</html>

Date Picker With Dropdowns

This focused composition keeps the Popover open after selecting a date so the user can change the month or year and confirm with Done. Selection and the Done command are implemented in the locally bundled TypeScript adapter.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Date Picker With Dropdowns</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
    <script src="../../js/date-picker-demo.umd.js"></script>
  </head>
  <body
    ng-app="datePickerDemo"
    ng-controller="DatePickerDemoController as picker"
    ng-cloak
    data-example="data-picker-with-dropdowns"
  >
    <main class="date-picker-dropdown-demo visual-example">
      <div class="date-picker-dropdown-field field">
        <label for="date-picker-with-dropdowns">Date</label>
        <span id="date-picker-dropdown-popover">
          <button
            id="date-picker-with-dropdowns"
            type="button"
            variant="outline"
            class="date-picker-trigger date-picker-trigger-between"
            popovertarget="popover-date-picker-with-dropdowns-1-content"
          >
            <span
              >{{ picker.dropdownDate ? picker.format(picker.dropdownDate) :
              'Pick a date' }}</span
            >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="m6 9 6 6 6-6"></path>
            </svg>
          </button>
          <aside
            class="calendar-popover-content date-picker-dropdown-content"
            aria-label="Choose a date with dropdowns"
            id="popover-date-picker-with-dropdowns-1-content"
            side="bottom"
            align="start"
            popover
          >
            <section
              ng-calendar
              data-calendar-generated
              data-month="2026-09"
              data-caption-layout="dropdown"
              data-start-year="2020"
              data-end-year="2030"
              ng-attr-data-value="{{ picker.dropdownDate }}"
              ng-on-angularcss:calendar-select="picker.selectDropdown($event.detail.value)"
            >
              <header>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Previous dropdown month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m15 18-6-6 6-6"></path>
                  </svg>
                </button>
                <h3></h3>
                <button
                  type="button"
                  size="icon"
                  variant="ghost"
                  aria-label="Next dropdown month"
                >
                  <svg
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m9 18 6-6-6-6"></path>
                  </svg>
                </button>
              </header>
              <div></div>
            </section>
            <footer class="date-picker-dropdown-footer">
              <button
                type="button"
                variant="outline"
                size="sm"
                ng-click="picker.finishDropdown()"
              >
                Done
              </button>
            </footer>
          </aside>
        </span>
      </div>
    </main>
  </body>
</html>

Installation

Install AngularCSS, load its stylesheet, and include the angular.css module in your AngularTS application. See Installation for the complete setup.

This component’s root directive is [ng-calendar]. Importing the package registers it with the AngularCSS angular.css module; there is no per-component JavaScript registration step.

Anatomy

Directive selectors

  • ng-calendar

Semantic structure

Use native elements for authored structure. Component classes are optional visual hooks when an HTML relationship is not specific enough.

API

Attributes and state

AttributeAccessPurpose
aria-currentInput/outputCurrent item or date state.
aria-disabledOutputSemantic disabled state.
aria-labelInput/outputAccessible name when visible text is insufficient.
aria-labelledbyOutputID of the element that supplies the accessible name.
aria-liveOutputAnnouncement priority for updates to a live region.
aria-pressedInput/outputPressed state of a toggle control.
data-bookedOutputWhether a generated calendar day is booked.
data-booked-datesInputComma-separated ISO dates styled as booked.
data-calendar-generatedInputEnables generated month markup inside the authored Calendar shell.
data-calendar-presetInputGenerated calendar preset: single, multiple, or range.
data-caption-layoutInputCaption controls: label or dropdown.
data-columnsInputNumber of columns used for calendar grid keyboard movement; defaults to 7.
data-disabled-afterInputLast selectable date as an ISO date.
data-disabled-beforeInputFirst selectable date as an ISO date.
data-disabled-datesInputComma-separated ISO dates that cannot be selected.
data-end-yearInputFinal year offered by a dropdown caption.
data-min-nightsInputMinimum number of nights accepted by range selection.
data-monthInput/outputDisplayed month in YYYY-MM form.
data-monthsOutputNumber of month grids currently rendered.
data-number-of-monthsInputNumber of consecutive months to render.
data-outsideInput/outputWhether a day belongs to an adjacent month.
data-range-endOutputMarks the final day in the selected range.
data-range-end-valueInput/outputSelected range end as an ISO date.
data-range-invalidOutputWhether the pending range violates the minimum-night constraint.
data-range-middleOutputMarks a day between the selected range boundaries.
data-range-startOutputMarks the first day in the selected range.
data-range-start-valueInput/outputSelected range start as an ISO date.
data-selection-modeInputSelection behavior: single, multiple, or range.
data-show-outside-daysInputShows dates from adjacent months when true.
data-show-week-numbersInput/outputShows ISO-style week numbers when true.
data-start-yearInputFirst year offered by a dropdown caption.
data-valueInput/outputSelected ISO date for single selection.
data-valuesInput/outputComma-separated selected ISO dates for multiple selection.
data-week-startInputFirst weekday as an integer from 0 (Sunday) to 6 (Saturday).
dirInputText and interaction direction: ltr or rtl.
langInputLanguage used for generated labels and localized text.
selectedOutputSelected value reflected by the component.
tabindexInput/outputKeyboard focus order for composite descendants.
valueOutputNative value or authored component value.

Input attributes are read from authored HTML. Output attributes are maintained by AngularCSS for CSS and testing. Input/output attributes may be authored for a controlled initial state and are then synchronized by the directive.

CSS custom properties

VariablePurpose
--calendar-cell-sizeWidth and height of calendar controls and day cells.

DOM events

  • angularcss:calendar-month-change
  • angularcss:calendar-range-invalid
  • angularcss:calendar-select

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

The directive owns generated Gregorian month grids, local-date navigation, selectable day state, range and multiple-selection signaling, disabled and booked constraints, caption controls, week numbers, keyboard grid movement, and synchronized authored attributes. AngularTS remains responsible for application models, parsed text, commands, validation, and composed popover state. Natural-language and non-Gregorian conversion remain explicit application adapters; the packaged Date Picker demo uses locally bundled chrono-node without adding a second model implementation.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Give the calendar or its visible title a useful accessible name. Generated weekdays are column headers; week numbers are row headers; day buttons expose selected, current, disabled, outside, booked, and range state. Arrow keys, Home, End, Page Up, and Page Down move through the date grid, while RTL reverses horizontal movement. Date Picker triggers must keep an accessible name and preserve focus through the composed Popover.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target [ng-calendar], semantic descendants, component classes, and generated state with ordinary CSS. Keep behavior and accessible state in the TypeScript directive; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.