diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index 58d94001..7f71c10e 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -52,6 +52,7 @@
   - [Format Bytes](/components/format-bytes.md)
   - [Format Number](/components/format-number.md)
   - [Include](/components/include.md)
+  - [Relative Time](/components/relative-time.md)
   - [Resize Observer](/components/resize-observer.md)
   - [Theme](/components/theme.md)
 
diff --git a/docs/components/relative-time.md b/docs/components/relative-time.md
new file mode 100644
index 00000000..5561b70c
--- /dev/null
+++ b/docs/components/relative-time.md
@@ -0,0 +1,61 @@
+# Relative Time
+
+[component-header:sl-relative-time]
+
+Outputs a localized time phrase relative to the current time.
+
+Localization is handled by the browser's [Intl.RelativeTimeFormat API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat) so there'e no need to load language packs.
+
+```html preview
+<sl-relative-time date="2011-11-11T16:56:20-04:00"></sl-relative-time><br>
+```
+
+The `date` prop must be a [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object or a string that [`Date.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) can interpret. When using strings, avoid ambiguous dates such as `03/04/2020` which can be interpreted as March 4 or April 3 depending on the user's browser and locale. Instead, use a valid [ISO 8601 date time string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#Date_Time_String_Format) to ensure proper parsing.
+
+?> [The Intl.RelativeTimeFormat API is available in all major browsers](https://caniuse.com/mdn-javascript_builtins_intl_relativetimeformat), but it first became available to Safari in version 14. If you need to support Safari 13, you'll need to [use a polyfill](https://github.com/catamphetamine/relative-time-format).
+
+## Examples
+
+### Keeping Time in Sync
+
+Use the `sync` attribute to update the displayed value as time passes.
+
+```html preview
+<div class="relative-time-sync">
+  <sl-relative-time sync></sl-relative-time>
+  <br><br>
+  <sl-button>Reset</sl-button>
+</div>
+
+<script>
+  const container = document.querySelector('.relative-time-sync');
+  const button = container.querySelector('sl-button');
+  const relativeTime = container.querySelector('sl-relative-time');
+
+  relativeTime.date = new Date();
+  button.addEventListener('click', () => relativeTime.date = new Date());
+</script>
+```
+
+### Formatting Styles
+
+You can change the way times are formatted with the `format` attribute. Note that some locales may show the same result for `narrow` and `short` formats.
+
+```html preview
+<sl-relative-time date="2020-07-15T09:17:00" format="narrow"></sl-relative-time><br>
+<sl-relative-time date="2020-07-15T09:17:00" format="short"></sl-relative-time><br>
+<sl-relative-time date="2020-07-15T09:17:00" format="long"></sl-relative-time>
+```
+
+### Localization
+
+Use the `locale` attribute to set the desired locale.
+
+```html preview
+English: <sl-relative-time date="2020-07-15T09:17:00" locale="en-US"></sl-relative-time><br>
+Chinese: <sl-relative-time date="2020-07-15T09:17:00" locale="zh-CN"></sl-relative-time><br>
+German: <sl-relative-time date="2020-07-15T09:17:00" locale="de-DE"></sl-relative-time><br>
+Russian: <sl-relative-time date="2020-07-15T09:17:00" locale="ru-RU"></sl-relative-time>
+```
+
+[component-metadata:sl-relative-time]
diff --git a/docs/getting-started/changelog.md b/docs/getting-started/changelog.md
index 664cea8c..02ab789d 100644
--- a/docs/getting-started/changelog.md
+++ b/docs/getting-started/changelog.md
@@ -9,6 +9,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
 ## Next
 
 - Added `sl-format-number` component
+- Added `sl-relative-time` component
 - Added `closable` prop to `sl-tab`
 - Added experimental `sl-resize-observer` utility
 - Added experimental `sl-theme` utility and updated theming documentation
diff --git a/src/components.d.ts b/src/components.d.ts
index eaf719dd..8711be7d 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -897,6 +897,24 @@ export namespace Components {
          */
         "value": number;
     }
+    interface SlRelativeTime {
+        /**
+          * The date from which to calculate time from.
+         */
+        "date": Date | string;
+        /**
+          * The formatting style to use.
+         */
+        "format": 'long' | 'short' | 'narrow';
+        /**
+          * The locale to use when formatting the number.
+         */
+        "locale": string;
+        /**
+          * When `auto`, values such as "yesterday" and "tomorrow" will be shown when possible. When `always`, values such as "1 day ago" and "in 1 day" will be shown.
+         */
+        "numeric": 'always' | 'auto';
+    }
     interface SlResizeObserver {
     }
     interface SlResponsiveEmbed {
@@ -1434,6 +1452,12 @@ declare global {
         prototype: HTMLSlRatingElement;
         new (): HTMLSlRatingElement;
     };
+    interface HTMLSlRelativeTimeElement extends Components.SlRelativeTime, HTMLStencilElement {
+    }
+    var HTMLSlRelativeTimeElement: {
+        prototype: HTMLSlRelativeTimeElement;
+        new (): HTMLSlRelativeTimeElement;
+    };
     interface HTMLSlResizeObserverElement extends Components.SlResizeObserver, HTMLStencilElement {
     }
     var HTMLSlResizeObserverElement: {
@@ -1544,6 +1568,7 @@ declare global {
         "sl-radio": HTMLSlRadioElement;
         "sl-range": HTMLSlRangeElement;
         "sl-rating": HTMLSlRatingElement;
+        "sl-relative-time": HTMLSlRelativeTimeElement;
         "sl-resize-observer": HTMLSlResizeObserverElement;
         "sl-responsive-embed": HTMLSlResponsiveEmbedElement;
         "sl-select": HTMLSlSelectElement;
@@ -2477,6 +2502,24 @@ declare namespace LocalJSX {
          */
         "value"?: number;
     }
+    interface SlRelativeTime {
+        /**
+          * The date from which to calculate time from.
+         */
+        "date"?: Date | string;
+        /**
+          * The formatting style to use.
+         */
+        "format"?: 'long' | 'short' | 'narrow';
+        /**
+          * The locale to use when formatting the number.
+         */
+        "locale"?: string;
+        /**
+          * When `auto`, values such as "yesterday" and "tomorrow" will be shown when possible. When `always`, values such as "1 day ago" and "in 1 day" will be shown.
+         */
+        "numeric"?: 'always' | 'auto';
+    }
     interface SlResizeObserver {
         /**
           * Emitted when the element is resized.
@@ -2862,6 +2905,7 @@ declare namespace LocalJSX {
         "sl-radio": SlRadio;
         "sl-range": SlRange;
         "sl-rating": SlRating;
+        "sl-relative-time": SlRelativeTime;
         "sl-resize-observer": SlResizeObserver;
         "sl-responsive-embed": SlResponsiveEmbed;
         "sl-select": SlSelect;
@@ -2912,6 +2956,7 @@ declare module "@stencil/core" {
             "sl-radio": LocalJSX.SlRadio & JSXBase.HTMLAttributes<HTMLSlRadioElement>;
             "sl-range": LocalJSX.SlRange & JSXBase.HTMLAttributes<HTMLSlRangeElement>;
             "sl-rating": LocalJSX.SlRating & JSXBase.HTMLAttributes<HTMLSlRatingElement>;
+            "sl-relative-time": LocalJSX.SlRelativeTime & JSXBase.HTMLAttributes<HTMLSlRelativeTimeElement>;
             "sl-resize-observer": LocalJSX.SlResizeObserver & JSXBase.HTMLAttributes<HTMLSlResizeObserverElement>;
             "sl-responsive-embed": LocalJSX.SlResponsiveEmbed & JSXBase.HTMLAttributes<HTMLSlResponsiveEmbedElement>;
             "sl-select": LocalJSX.SlSelect & JSXBase.HTMLAttributes<HTMLSlSelectElement>;
diff --git a/src/components/relative-time/relative-time.tsx b/src/components/relative-time/relative-time.tsx
new file mode 100644
index 00000000..336105b2
--- /dev/null
+++ b/src/components/relative-time/relative-time.tsx
@@ -0,0 +1,45 @@
+import { Component, Prop, State, h } from '@stencil/core';
+
+/**
+ * @since 2.0
+ * @status stable
+ */
+
+@Component({
+  tag: 'sl-relative-time',
+  shadow: true
+})
+export class RelativeTime {
+  @State() displayTime = '';
+
+  /** The date from which to calculate time from. */
+  @Prop() date: Date | string;
+
+  /** The locale to use when formatting the number. */
+  @Prop() locale: string;
+
+  /** The formatting style to use. */
+  @Prop() format: 'long' | 'short' | 'narrow' = 'long';
+
+  /**
+   * When `auto`, values such as "yesterday" and "tomorrow" will be shown when possible. When `always`, values such as
+   * "1 day ago" and "in 1 day" will be shown.
+   */
+  @Prop() numeric: 'always' | 'auto' = 'auto';
+
+  render() {
+    const date = new Date(this.date);
+
+    if (isNaN(date.getSeconds())) {
+      return '';
+    }
+
+    // // @ts-ignore - https://caniuse.com/mdn-javascript_builtins_intl_relativetimeformat
+    // new Intl.RelativeTimeFormat(this.locale, {
+    //   numeric: this.numeric,
+    //   style: this.type
+    // }).format(this.value, this.unit);
+
+    return <time dateTime={date.toISOString()}>{this.displayTime}</time>;
+  }
+}