Date Picker

Enter a date, time, or range directly, or choose it from a calendar.

Live preview
Interact with the component to see results here.
View code
HTML
<sy-datepicker
  variant="date"
  mode="day"
  placeholder="Select date"
  format="yyyy-MM-dd"
  year="2026"
  month="10"
  day="15"
  hour="09"
  minute="30"
  second="00"
  name="date"
  id="sample"
  aria-label="Select date"
></sy-datepicker>

Usage guide

#

Use for date and time selection. Choose variant to match the required value.

  1. Write the error message in the error slot.

    Inside the component, add <span slot="error">Error message</span>. You can include links and other guidance as well as text. For inputs supporting noNativeValidity, enable it to show this guidance instead of a browser popup. Switch always displays errors below the component.

  2. Report business rule failures with setCustomError().

    For example, if the server rejects a duplicate value, update the error slot and call setCustomError(). This method does not take a message argument. A custom error also blocks form submission.

  3. Clear the error after resolving it and check whether submission is allowed.

    Use clearCustomError() to clear a business rule error. Required-field and format validation remain active. await checkValidity() returns true or false; reportValidity() validates and displays errors. Read valid named values through FormData on submission.

Date

Use date. Set the day, month, or year selection unit with mode.

Date and time

Use datetime to select both a date and a time.

Range

Use range to collect a start and end date.

Time

Use time to select a time without a date.

Display and form integration
format uses yyyy, MM, dd, hh, mm, and ss. Connect forms with name and required. selected reports confirmed selection; changed reports input changes.

Examples

#

Date and initial value

October 15, 2026 is shown initially. Change the date using the calendar or text input.

View code
HTML
<sy-datepicker
  year="2026"
  month="10"
  day="15"
  hour="09"
  minute="30"
  second="00"
  format="yyyy-MM-dd"
  placeholder="Select date"
></sy-datepicker>

Date and time

Choose a date from the calendar and set its time.

View code
HTML
<sy-datepicker
  year="2026"
  month="10"
  day="15"
  hour="09"
  minute="30"
  second="00"
  variant="datetime"
  format="yyyy-MM-dd hh:mm:ss"
></sy-datepicker>

Range selection

Choose a start and end date. Set both endpoints and inspect the result.

View code
HTML
<sy-datepicker
  variant="range"
  format="yyyy-MM-dd"
  placeholder="Range selection"
></sy-datepicker>

Time only

Enter hours, minutes, and seconds or select them from a list without displaying a date.

View code
HTML
<sy-datepicker
  year="2026"
  month="10"
  day="15"
  hour="09"
  minute="30"
  second="00"
  variant="time"
  format="hh:mm:ss"
  placeholder="Select time"
></sy-datepicker>

Select a month or year

When a specific day is unnecessary, such as for an aggregation period, change both the selection unit and display format.

View code
HTML
<div style="display:grid;gap:16px;width:100%">
  <sy-datepicker
    year="2026"
    month="10"
    day="15"
    hour="09"
    minute="30"
    second="00"
    mode="month"
    format="yyyy-MM"
    placeholder="Select month"
  ></sy-datepicker>
  <sy-datepicker
    year="2026"
    month="10"
    day="15"
    hour="09"
    minute="30"
    second="00"
    mode="year"
    format="yyyy"
    placeholder="Select year"
  ></sy-datepicker>
</div>

Workday calendar

Start on Monday and hide weekends. Pass weekday labels as a string ordered from Sunday through Saturday.

View code
HTML
<sy-datepicker
  year="2026"
  month="10"
  day="15"
  hour="09"
  minute="30"
  second="00"
  format="yyyy-MM-dd"
  mondaystart
  hideweekend
  datenames="Sun,Mon,Tue,Wed,Thu,Fri,Sat"
></sy-datepicker>

Place a calendar inline

When using sy-calendar directly, set its position to relative. Child Calendar components use zero-based months.

View code
HTML
<sy-calendar
  year="2026"
  month="9"
  day="15"
  mondaystart
  style="position:relative;align-self:center"
></sy-calendar>

Disabled and read only

Show the date while restricting selection and editing.

View code
HTML
<div style="display:grid;gap:16px;width:100%">
  <sy-datepicker
    year="2026"
    month="10"
    day="15"
    hour="09"
    minute="30"
    second="00"
    format="yyyy-MM-dd"
    disabled
  ></sy-datepicker>
  <sy-datepicker
    year="2026"
    month="10"
    day="15"
    hour="09"
    minute="30"
    second="00"
    format="yyyy-MM-dd"
    readonly
  ></sy-datepicker>
</div>

Events and payloads

Interact with the component and inspect the latest event name and detail. The code includes subscriptions to events emitted by this component and its children.

View code
HTML
<sy-datepicker
  variant="date"
  mode="day"
  placeholder="Select date"
  format="yyyy-MM-dd"
  year="2026"
  month="10"
  day="15"
  hour="09"
  minute="30"
  second="00"
  name="date"
  id="sample"
  aria-label="Select date"
></sy-datepicker>
<output id="demo-events" aria-live="polite">Interact with the component to see
  its latest event and payload.</output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  for (const name of ["changed", "selected", "closed", "entered", "mode-changed"]) {
    document.addEventListener(name, event => {
      document.querySelector('#demo-events').textContent =
        `${event.target.localName} · ${name}: ${describeResult(event.detail)}`;
    });
  }
</script>

Display a range on the calendar

When using Calendar directly, pass rangestart and rangeend as objects. Calendar components use zero-based months. active identifies the endpoint being edited: start or end.

View code
HTML
<sy-calendar
  year="2026"
  month="9"
  day="15"
  active="start"
  variant="range"
  id="sample"
  style="position:relative"
></sy-calendar>

<script type="module">
  const component1 = document.querySelector("#sample");
  Object.assign(component1, {
    "rangestart": {
      "year": 2026,
      "month": 9,
      "day": 10
    },
    "rangeend": {
      "year": 2026,
      "month": 9,
      "day": 20
    }
  });
</script>

Time separator and confirmation button

When using Timepicker directly, timeSeparator sets the symbol between hours, minutes, and seconds. hideButton hides the confirmation button.

View code
HTML
<sy-timepicker
  hour="9"
  minute="30"
  second="0"
  timeseparator="."
  hidebutton
  style="position:relative"
></sy-timepicker>

Forms and validation

Submission requires a date. Select one, then inspect the submitted value and custom errors.

View code
HTML
<form style="display:grid;gap:16px">
  <sy-datepicker
    name="schedule"
    required
    format="yyyy-MM-dd"
    placeholder="Required date"
    id="sample"
  ><span slot="error">Choose a date.</span></sy-datepicker>
  <div style="display:flex;flex-wrap:wrap;gap:8px">
    <sy-button type="submit" variant="primary">Submit</sy-button>
    <sy-button type="reset">Reset</sy-button>
  </div>
</form>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Check validity</sy-button>
  <sy-button id="action-1" size="small">Show error</sy-button>
  <sy-button id="action-2" size="small">Clear error</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.checkValidity();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget1 = document.querySelector("#sample");
  document.querySelector('#action-1').addEventListener('click', async () => {
    const result = await actionTarget1.setCustomError();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget2 = document.querySelector("#sample");
  document.querySelector('#action-2').addEventListener('click', async () => {
    const result = await actionTarget2.clearCustomError();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  document.querySelector('form').addEventListener('submit', event => {
    event.preventDefault();
    document.querySelector('#demo-result').textContent = describeResult([...new FormData(event
      .currentTarget)]);
  });
</script>

Read validation results and error states

Validate before submitting or display errors on screen. Check an empty required field, then fill it to see how the return value changes. Querying the state distinguishes custom errors from required-field errors.

View code
HTML
<form style="display:grid;gap:16px">
  <sy-datepicker
    name="schedule"
    required
    format="yyyy-MM-dd"
    placeholder="Required date"
    id="sample"
  ><span slot="error">Choose a date.</span></sy-datepicker>
  <div style="display:flex;flex-wrap:wrap;gap:8px">
    <sy-button type="submit" variant="primary">Submit</sy-button>
    <sy-button type="reset">Reset</sy-button>
  </div>
</form>
<div class="demo-actions"
  style="display:flex;flex-wrap:wrap;gap:8px;margin-top:16px"
>
  <sy-button id="action-0" size="small">Check validity</sy-button>
  <sy-button id="action-1" size="small">Show error</sy-button>
  <sy-button id="action-2" size="small">Clear error</sy-button>
  <sy-button id="action-3" size="small">Validate with errors</sy-button>
  <sy-button id="action-4" size="small">Query validation state</sy-button>
</div>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  const actionTarget0 = document.querySelector("#sample");
  document.querySelector('#action-0').addEventListener('click', async () => {
    const result = await actionTarget0.checkValidity();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget1 = document.querySelector("#sample");
  document.querySelector('#action-1').addEventListener('click', async () => {
    const result = await actionTarget1.setCustomError();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget2 = document.querySelector("#sample");
  document.querySelector('#action-2').addEventListener('click', async () => {
    const result = await actionTarget2.clearCustomError();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget3 = document.querySelector("#sample");
  document.querySelector('#action-3').addEventListener('click', async () => {
    const result = await actionTarget3.reportValidity();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  const actionTarget4 = document.querySelector("#sample");
  document.querySelector('#action-4').addEventListener('click', async () => {
    const result = await actionTarget4.getStatus();
    document.querySelector('#demo-result').textContent = describeResult(result);
  });
  document.querySelector('form').addEventListener('submit', event => {
    event.preventDefault();
    document.querySelector('#demo-result').textContent = describeResult([...new FormData(event
      .currentTarget)]);
  });
</script>

Custom error messages

Display a custom error for server-side duplicate checks or business rules. Change the message below and submit to verify that it is blocked. After clearing the error, required-field constraints must still be satisfied.

View code
HTML
<label for="error-message">Error message to display</label><input
  id="error-message"
  value="The server did not accept this value. Please review it."
  type="text"
>
<form style="display:grid;gap:16px">
  <sy-datepicker
    no-native-validity
    name="schedule"
    required
    format="yyyy-MM-dd"
    placeholder="Required date"
    id="sample"
  ><span slot="error">Choose a date.</span></sy-datepicker>
  <div style="display:flex;flex-wrap:wrap;gap:8px">
    <sy-button type="submit" variant="primary">Submit</sy-button>
    <sy-button type="reset">Reset</sy-button>
  </div>
</form>
<div class="demo-actions">
  <sy-button id="show-custom-error" variant="primary">Show error</sy-button>
  <sy-button id="clear-custom-error">Clear error</sy-button>
</div>
<output id="custom-error-result" aria-live="polite"></output>
<output id="demo-result" aria-live="polite"></output>

<script type="module">
  const describeResult = value => JSON.stringify(value, (_key, item) => {
    if (item instanceof File) return {
      name: item.name,
      size: item.size,
      type: item.type
    };
    if (item instanceof Element) return `<${item.localName}>`;
    return item;
  }) ?? 'Done';
  await (async function customErrorSetup(root) {
    const field = root.querySelector('#sample');
    const message = root.querySelector('[slot="error"]');
    const input = root.querySelector('#error-message');
    const output = root.querySelector('#custom-error-result');
    const update = async () => {
      message.textContent = input.value.trim() || _msg("m_4eea8cef81c6");
      await field.setCustomError();
      output.textContent = _msg("m_e00bd46236d3", [message.textContent]);
    };
    input.addEventListener('input', update);
    root.querySelector('#show-custom-error').addEventListener('click', update);
    root.querySelector('#clear-custom-error').addEventListener('click', async () => {
      await field.clearCustomError();
      output.textContent = await field.checkValidity() ? _msg("m_c454251167b2") : _msg(
        "m_5b8cb48627e5");
    });
    root.querySelector('form').addEventListener('invalid', () => {
      output.textContent = _msg("m_c702c7778166");
    }, true);
    root.querySelector('form').addEventListener('reset', () => {
      output.textContent = _msg("m_b90c2b4dc30f");
    });
    await update();
  })(document);
  document.querySelector('form').addEventListener('submit', event => {
    event.preventDefault();
    document.querySelector('#demo-result').textContent = describeResult([...new FormData(event
      .currentTarget)]);
  });
</script>

API reference

#

Hover over a name or focus it with the keyboard to see the code. On touch screens, tap the name.

<sy-datepicker>

Properties

Attribute / PropertyTypeDefaultDescription
'day' | 'month' | 'year''day'Date selection unit: day, month, or year.
'date' | 'datetime' | 'range' | 'time''date'Selection type: date, date and time, range, or time.
booleanfalseBlock user interaction and keyboard focus.
booleanfalseDisplay the current value while preventing edits.
booleanfalseFail form validation when no value is provided.
stringundefinedYear.
stringundefinedMonth. Date Picker uses 1–12; child Calendar components use 0–11.
stringundefinedDay of the month.
stringundefinedHour, from 0 to 23.
stringundefinedMinute, from 0 to 59.
stringundefinedSecond, from 0 to 59.
string'Su,Mo,Tu,We,Th,Fr,Sa'Comma-separated weekday names, from Sunday through Saturday.
booleanfalseStart the week on Monday.
booleanfalseHide Saturdays and Sundays in the calendar.
string''Placeholder shown when the value is empty.
string'yyyy-MM-dd hh:mm:ss'Display format combining the yyyy, MM, dd, hh, mm, and ss tokens.
string''Field name used in FormData.
booleanfalseUse the app's error UI instead of the browser's built-in error display. checkValidity still performs validation.

Events

EventDetailDescription
CustomEvent<unknown>Emitted when the value or selection state changes.
CustomEvent<unknown>Emitted when the user selects an item.

Methods

MethodReturnsDescription
Promise<string>Return the current validation state.
Promise<void>Set a custom error state.
Promise<void>Clear the custom error state.
Promise<boolean>Return true if the current constraints are satisfied, otherwise false.
Promise<boolean>Validate the current value and display errors to the user.

Slots

SlotDescription
Validation error message.

<sy-calendar>

Properties

Attribute / PropertyTypeDefaultDescription
'day' | 'month' | 'year''day'Date selection unit: day, month, or year.
'date' | 'datetime' | 'range' | 'time''date'Panel to display: date, date and time, range, or time.
string'hh:mm:ss'Format used to display and parse values. See the usage guide for tokens or format values.
stringundefinedRange endpoint currently being edited: start or end.
numberundefinedYear.
numberundefinedMonth. Date Picker uses 1–12; child Calendar components use 0–11.
numberundefinedDay of the month.
numberundefinedHour, from 0 to 23.
numberundefinedMinute, from 0 to 59.
numberundefinedSecond, from 0 to 59.
{year: number, month: number, day: number }undefinedStart date of the selected range. month is zero-based.

Pass objects and arrays as JavaScript properties.

{year: number, month: number, day: number }undefinedEnd date of the selected range. month is zero-based.

Pass objects and arrays as JavaScript properties.

string'Su,Mo,Tu,We,Th,Fr,Sa'Comma-separated weekday names, from Sunday through Saturday.
booleanfalseStart the week on Monday.
booleanfalseHide Saturdays and Sundays in the calendar.

Events

EventDetailDescription
CustomEvent<unknown>Emitted when the user selects an item.
CustomEvent<unknown>Read the result from the event's detail.

<sy-date-calendar>

Properties

Attribute / PropertyTypeDefaultDescription
'day' | 'month' | 'year' | 'decade'undefinedDay, month, year, or decade view.
{year: number, month: number, day: number, hour: number, minute: number, second: number}{ year: new Date().getFullYear(), month: new Date().getMonth(), day: new Date().getDate(), hour: new Date().getHours(), minute: new Date().getMinutes(), second: new Date().getSeconds() }Object containing year, month, day, hour, minute, and second. month is zero-based.

Pass objects and arrays as JavaScript properties.

'start' | 'end'undefinedAssign the start or end role in range selection.
stringundefinedRange endpoint currently being edited: start or end.
{year: number, month: number, day: number }undefinedStart date of the selected range. month is zero-based.

Pass objects and arrays as JavaScript properties.

{year: number, month: number, day: number }undefinedEnd date of the selected range. month is zero-based.

Pass objects and arrays as JavaScript properties.

stringundefinedDate under the pointer during range selection.
string'Su,Mo,Tu,We,Th,Fr,Sa'Comma-separated weekday names, from Sunday through Saturday.
booleanfalseStart the week on Monday.
booleanfalseHide Saturdays and Sundays in the calendar.
Datenew Date()Reference date for the current calendar view, passed as a Date object.

Pass objects and arrays as JavaScript properties.

Events

EventDetailDescription
CustomEvent<unknown>Emitted when the value or selection state changes.
CustomEvent<unknown>Emitted when the user selects an item.
CustomEvent<unknown>Read the result from the event's detail.
CustomEvent<unknown>Read the result from the event's detail.

<sy-date-time-calendar>

Properties

Attribute / PropertyTypeDefaultDescription
'day' | 'month' | 'year' | 'decade''day'Day, month, year, or decade view.
{year: number, month: number, day: number, hour: number, minute: number, second: number}{ year: new Date().getFullYear(), month: new Date().getMonth(), day: new Date().getDate(), hour: new Date().getHours(), minute: new Date().getMinutes(), second: new Date().getSeconds() }Object containing year, month, day, hour, minute, and second. month is zero-based.

Pass objects and arrays as JavaScript properties.

string'Su,Mo,Tu,We,Th,Fr,Sa'Comma-separated weekday names, from Sunday through Saturday.
booleanfalseStart the week on Monday.
booleanfalseHide Saturdays and Sundays in the calendar.

Events

EventDetailDescription
CustomEvent<unknown>Emitted when the user selects an item.

<sy-range-calendar>

Properties

Attribute / PropertyTypeDefaultDescription
'day' | 'month' | 'year'undefinedDay, month, or year view.
stringundefinedEndpoint currently being edited: start or end.
{year: number, month: number, day: number, hour: number, minute: number, second: number}undefinedObject containing year, month, day, hour, minute, and second. month is zero-based.

Pass objects and arrays as JavaScript properties.

{ year: number, month: number, day: number }undefinedStart date of the selected range. month is zero-based.

Pass objects and arrays as JavaScript properties.

{ year: number, month: number, day: number }undefinedEnd date of the selected range. month is zero-based.

Pass objects and arrays as JavaScript properties.

string'Su,Mo,Tu,We,Th,Fr,Sa'Comma-separated weekday names, from Sunday through Saturday.
booleanfalseStart the week on Monday.
booleanfalseHide Saturdays and Sundays in the calendar.

Events

EventDetailDescription
CustomEvent<unknown>Emitted when the user selects an item.

<sy-timepicker>

Properties

Attribute / PropertyTypeDefaultDescription
number0Hour, from 0 to 23.
number0Minute, from 0 to 59.
number0Second, from 0 to 59.
booleanfalseHide the time selection panel's confirmation button.
string':'Separator character between time units.
string'hh:mm:ss'Format used to display and parse values. See the usage guide for tokens or format values.

Events

EventDetailDescription
CustomEvent<unknown>Emitted when the user selects an item.
CustomEvent<unknown>Emitted when the value or selection state changes.