Calendar
Presents a calendar surface for date selection.
See it in context
Preview
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
| 29 | 30 | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | 31 | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
| 29 | 30 | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | 31 | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
| 29 | 30 | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | 31 | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Copy a working example
Usage
Astro examples assume UIPrimitives is mounted once in your root layout. Do not add the runtime next to each component instance.
---
import {
Calendar,
Field,
Label
} from '@santi020k/lumen-astro'
---
<div style="display: grid; gap: 1rem; max-width: 42rem;">
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));">
<Field>
<Label id="ex-calendar-basic-label">Project month</Label>
<Calendar aria-labelledby="ex-calendar-basic-label" month="2026-07" />
</Field>
<Field>
<Label id="ex-calendar-selected-label">Selected milestone</Label>
<Calendar aria-labelledby="ex-calendar-selected-label" value="2026-07-14" />
</Field>
</div>
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));">
<Field>
<Label id="ex-calendar-bounds-label">Booking window</Label>
<Calendar
aria-labelledby="ex-calendar-bounds-label"
max="2026-07-24"
min="2026-07-08"
month="2026-07"
/>
</Field>
<form style="display: grid; gap: 0.75rem;">
<Field>
<Label id="ex-calendar-form-label">Delivery date</Label>
<Calendar
aria-labelledby="ex-calendar-form-label"
max="2026-08-31"
min="2026-07-01"
month="2026-07"
name="deliveryDate"
value="2026-07-20"
/>
</Field>
<button class="ui-button ui-button--default ui-button--default-size" type="submit">Save date</button>
</form>
</div>
</div>---
import {
Calendar,
Field,
Label
} from '@santi020k/lumen-astro'
---
<div style="display: grid; gap: 1rem; max-width: 42rem;">
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));">
<Field>
<Label id="ex-calendar-basic-label">Project month</Label>
<Calendar aria-labelledby="ex-calendar-basic-label" month="2026-07" />
</Field>
<Field>
<Label id="ex-calendar-selected-label">Selected milestone</Label>
<Calendar aria-labelledby="ex-calendar-selected-label" value="2026-07-14" />
</Field>
</div>
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));">
<Field>
<Label id="ex-calendar-bounds-label">Booking window</Label>
<Calendar
aria-labelledby="ex-calendar-bounds-label"
max="2026-07-24"
min="2026-07-08"
month="2026-07"
/>
</Field>
<form style="display: grid; gap: 0.75rem;">
<Field>
<Label id="ex-calendar-form-label">Delivery date</Label>
<Calendar
aria-labelledby="ex-calendar-form-label"
max="2026-08-31"
min="2026-07-01"
month="2026-07"
name="deliveryDate"
value="2026-07-20"
/>
</Field>
<button class="ui-button ui-button--default ui-button--default-size" type="submit">Save date</button>
</form>
</div>
</div>import { Calendar, Field, Label } from '@santi020k/lumen-react'
export const Example = () => (
<>
<div style={{ display: 'grid', gap: '1rem', maxWidth: '42rem' }}>
<div style={{ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(auto-fit, minmax(17rem, 1fr))' }}>
<Field>
<Label id="ex-calendar-basic-label">Project month</Label>
<Calendar aria-labelledby="ex-calendar-basic-label" month="2026-07" />
</Field>
<Field>
<Label id="ex-calendar-selected-label">Selected milestone</Label>
<Calendar aria-labelledby="ex-calendar-selected-label" value="2026-07-14" />
</Field>
</div>
<div style={{ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(auto-fit, minmax(17rem, 1fr))' }}>
<Field>
<Label id="ex-calendar-bounds-label">Booking window</Label>
<Calendar
aria-labelledby="ex-calendar-bounds-label"
max="2026-07-24"
min="2026-07-08"
month="2026-07"
/>
</Field>
<form style={{ display: 'grid', gap: '0.75rem' }}>
<Field>
<Label id="ex-calendar-form-label">Delivery date</Label>
<Calendar
aria-labelledby="ex-calendar-form-label"
max="2026-08-31"
min="2026-07-01"
month="2026-07"
name="deliveryDate"
value="2026-07-20"
/>
</Field>
<button className="ui-button ui-button--default ui-button--default-size" type="submit">Save date</button>
</form>
</div>
</div>
</>
)import { Calendar, Field, Label } from '@santi020k/lumen-react'
export const Example = () => (
<>
<div style={{ display: 'grid', gap: '1rem', maxWidth: '42rem' }}>
<div style={{ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(auto-fit, minmax(17rem, 1fr))' }}>
<Field>
<Label id="ex-calendar-basic-label">Project month</Label>
<Calendar aria-labelledby="ex-calendar-basic-label" month="2026-07" />
</Field>
<Field>
<Label id="ex-calendar-selected-label">Selected milestone</Label>
<Calendar aria-labelledby="ex-calendar-selected-label" value="2026-07-14" />
</Field>
</div>
<div style={{ display: 'grid', gap: '1rem', gridTemplateColumns: 'repeat(auto-fit, minmax(17rem, 1fr))' }}>
<Field>
<Label id="ex-calendar-bounds-label">Booking window</Label>
<Calendar
aria-labelledby="ex-calendar-bounds-label"
max="2026-07-24"
min="2026-07-08"
month="2026-07"
/>
</Field>
<form style={{ display: 'grid', gap: '0.75rem' }}>
<Field>
<Label id="ex-calendar-form-label">Delivery date</Label>
<Calendar
aria-labelledby="ex-calendar-form-label"
max="2026-08-31"
min="2026-07-01"
month="2026-07"
name="deliveryDate"
value="2026-07-20"
/>
</Field>
<button className="ui-button ui-button--default ui-button--default-size" type="submit">Save date</button>
</form>
</div>
</div>
</>
)<script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<div style="display: grid; gap: 1rem; max-width: 42rem;">
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));">
<lumen-field>
<lumen-label id="ex-calendar-basic-label">Project month</lumen-label>
<lumen-calendar aria-labelledby="ex-calendar-basic-label" month="2026-07"></lumen-calendar>
</lumen-field>
<lumen-field>
<lumen-label id="ex-calendar-selected-label">Selected milestone</lumen-label>
<lumen-calendar aria-labelledby="ex-calendar-selected-label" value="2026-07-14"></lumen-calendar>
</lumen-field>
</div>
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));">
<lumen-field>
<lumen-label id="ex-calendar-bounds-label">Booking window</lumen-label>
<lumen-calendar
aria-labelledby="ex-calendar-bounds-label"
max="2026-07-24"
min="2026-07-08"
month="2026-07"></lumen-calendar>
</lumen-field>
<form style="display: grid; gap: 0.75rem;">
<lumen-field>
<lumen-label id="ex-calendar-form-label">Delivery date</lumen-label>
<lumen-calendar
aria-labelledby="ex-calendar-form-label"
max="2026-08-31"
min="2026-07-01"
month="2026-07"
name="deliveryDate"
value="2026-07-20"></lumen-calendar>
</lumen-field>
<button class="ui-button ui-button--default ui-button--default-size" type="submit">Save date</button>
</form>
</div>
</div><script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<div style="display: grid; gap: 1rem; max-width: 42rem;">
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));">
<lumen-field>
<lumen-label id="ex-calendar-basic-label">Project month</lumen-label>
<lumen-calendar aria-labelledby="ex-calendar-basic-label" month="2026-07"></lumen-calendar>
</lumen-field>
<lumen-field>
<lumen-label id="ex-calendar-selected-label">Selected milestone</lumen-label>
<lumen-calendar aria-labelledby="ex-calendar-selected-label" value="2026-07-14"></lumen-calendar>
</lumen-field>
</div>
<div style="display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));">
<lumen-field>
<lumen-label id="ex-calendar-bounds-label">Booking window</lumen-label>
<lumen-calendar
aria-labelledby="ex-calendar-bounds-label"
max="2026-07-24"
min="2026-07-08"
month="2026-07"></lumen-calendar>
</lumen-field>
<form style="display: grid; gap: 0.75rem;">
<lumen-field>
<lumen-label id="ex-calendar-form-label">Delivery date</lumen-label>
<lumen-calendar
aria-labelledby="ex-calendar-form-label"
max="2026-08-31"
min="2026-07-01"
month="2026-07"
name="deliveryDate"
value="2026-07-20"></lumen-calendar>
</lumen-field>
<button class="ui-button ui-button--default ui-button--default-size" type="submit">Save date</button>
</form>
</div>
</div>Choose your target
Add this component
Choose the package for your runtime. All adapters share the Lumen stylesheet. Use the matching registry command when you want a local wrapper for that framework.
pnpm add @santi020k/lumen-astropnpm add @santi020k/lumen-astrolumen add Calendarlumen add Calendarpnpm add @santi020k/lumen-reactpnpm add @santi020k/lumen-reactlumen add Calendar --target reactlumen add Calendar --target reactpnpm add @santi020k/lumen-elementspnpm add @santi020k/lumen-elementslumen add Calendar --target elementslumen add Calendar --target elementsGlass
Add the glass prop to apply the shared blur, saturation, border, and highlight tokens. Glass reads best over vivid content, so place the surface above imagery or color.
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
| 29 | 30 | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | 31 | 1 | 2 |
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---
import { Calendar } from '@santi020k/lumen-astro'
---
<div class="docs-glass-demo">
<Calendar aria-label="July 2026" glass>
<strong>July 2026</strong>
<table>
<thead>
<tr><th>Mo</th><th>Tu</th><th>We</th><th>Th</th><th>Fr</th><th>Sa</th><th>Su</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td><td>13</td><td>14</td></tr>
<tr><td>15</td><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td></tr>
</tbody>
</table>
</Calendar>
</div>---
import { Calendar } from '@santi020k/lumen-astro'
---
<div class="docs-glass-demo">
<Calendar aria-label="July 2026" glass>
<strong>July 2026</strong>
<table>
<thead>
<tr><th>Mo</th><th>Tu</th><th>We</th><th>Th</th><th>Fr</th><th>Sa</th><th>Su</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td><td>13</td><td>14</td></tr>
<tr><td>15</td><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td></tr>
</tbody>
</table>
</Calendar>
</div>import { Calendar } from '@santi020k/lumen-react'
export const Example = () => (
<>
<div className="docs-glass-demo">
<Calendar aria-label="July 2026" glass>
<strong>July 2026</strong>
<table>
<thead>
<tr><th>Mo</th><th>Tu</th><th>We</th><th>Th</th><th>Fr</th><th>Sa</th><th>Su</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td><td>13</td><td>14</td></tr>
<tr><td>15</td><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td></tr>
</tbody>
</table>
</Calendar>
</div>
</>
)import { Calendar } from '@santi020k/lumen-react'
export const Example = () => (
<>
<div className="docs-glass-demo">
<Calendar aria-label="July 2026" glass>
<strong>July 2026</strong>
<table>
<thead>
<tr><th>Mo</th><th>Tu</th><th>We</th><th>Th</th><th>Fr</th><th>Sa</th><th>Su</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td><td>13</td><td>14</td></tr>
<tr><td>15</td><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td></tr>
</tbody>
</table>
</Calendar>
</div>
</>
)<script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<div class="docs-glass-demo">
<lumen-calendar aria-label="July 2026" glass>
<strong>July 2026</strong>
<table>
<thead>
<tr><th>Mo</th><th>Tu</th><th>We</th><th>Th</th><th>Fr</th><th>Sa</th><th>Su</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td><td>13</td><td>14</td></tr>
<tr><td>15</td><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td></tr>
</tbody>
</table>
</lumen-calendar>
</div><script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<div class="docs-glass-demo">
<lumen-calendar aria-label="July 2026" glass>
<strong>July 2026</strong>
<table>
<thead>
<tr><th>Mo</th><th>Tu</th><th>We</th><th>Th</th><th>Fr</th><th>Sa</th><th>Su</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td><td>11</td><td>12</td><td>13</td><td>14</td></tr>
<tr><td>15</td><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td><td>21</td></tr>
</tbody>
</table>
</lumen-calendar>
</div>API reference
Lumen-specific props and runtime attributes for the Astro primitive. React props follow the same names; Elements use equivalent kebab-case attributes where custom elements expose them.
| Attribute | Values | Default | Description |
|---|---|---|---|
| glass | boolean | "subtle" | "strong" | false | Applies the tokenized liquid-glass surface treatment with backdrop-filter fallbacks; "subtle" and "strong" adjust the fill intensity. |
| disabled | boolean | false | Disables month navigation, date selection, and the hidden form input. |
| max | YYYY-MM-DD string | - | Disables dates after the inclusive maximum date. |
| min | YYYY-MM-DD string | - | Disables dates before the inclusive minimum date. |
| month | YYYY-MM string | current or selected month | Sets the initially visible month. |
| name | string | - | Sets the name of the hidden input that stores the selected ISO date. |
| value | YYYY-MM-DD string | "" | Sets the selected date and hidden input value. |
| class, className | string | "" | Merges custom classes with the generated ui-* root classes. |
| ...native attributes | HTML attributes | - | Forwards standard attributes to the root element unless the component consumes them. |
Keyboard interactions
Keyboard behavior provided by the Astro UIPrimitives runtime for this component.
| Key | Action |
|---|---|
| Enter, Space on a day | Select the focused day, update the hidden input, and dispatch native input and change events from that input. |
| ArrowRight, ArrowLeft | Move day focus by one day. |
| ArrowDown, ArrowUp | Move day focus by one week. |
| Home, End | Move focus to the first or last day in the current week row. |
| PageDown, PageUp | Move focus to the same date in the next or previous month. |