Skip to content

Commit

Permalink
feat: allow title prop to be overridable (#44)
Browse files Browse the repository at this point in the history
Closes #43
  • Loading branch information
metonym authored Apr 20, 2024
1 parent c5a4ab2 commit 72a02ce
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 8 deletions.
52 changes: 47 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@ Use the `format` prop to customize the [format](https://day.js.org/docs/en/displ
<Time relative format="dddd @ h:mm A · MMMM D, YYYY" />
```

When using `relative`, the `time` element will set the formatted timestamp as the `title` attribute. Specify a custom `title` to override this.

```svelte
<Time relative title="Custom title" />
```

Set the value to `undefined` to omit the `title` altogether.

```svelte
<Time relative title={undefined} />
```

### Live updates

Set `live` to `true` for a live updating relative timestamp. The default refresh interval is 60 seconds.
Expand All @@ -113,7 +125,9 @@ To customize the interval, pass a value to `live` in milliseconds (ms).

### `svelteTime` action

Use the `svelteTime` action to format a timestamp in a raw HTML element.
An alternative to the `Time` component is to use the `svelteTime` action to format a timestamp in a raw HTML element.

The API is the same as the `Time` component.

```svelte
<script>
Expand All @@ -128,7 +142,13 @@ Use the `svelteTime` action to format a timestamp in a raw HTML element.
format: "dddd @ h:mm A · MMMM D, YYYY",
}}
/>
```

#### Relative time

Set `relative` to `true` to use relative time.

```svelte
<time
use:svelteTime={{
relative: true,
Expand All @@ -145,6 +165,26 @@ Use the `svelteTime` action to format a timestamp in a raw HTML element.
/>
```

To customize or omit the `title` attribute, use the `title` prop.

```svelte
<time
use:svelteTime={{
relative: true,
title: "Custom title",
timestamp: "2021-02-02",
}}
/>
<time
use:svelteTime={{
relative: true,
title: undefined,
timestamp: "2021-02-02",
}}
/>
```

Similar to the `Time` component, the `live` prop only works with relative time.

```svelte
Expand All @@ -162,24 +202,26 @@ Specify a custom update interval using the `live` prop.
<time
use:svelteTime={{
relative: true,
live: 30 * 1_000, // update every 30 seconds
live: 30 * 1_000, // Update every 30 seconds
}}
/>
```

### `dayjs` export

`dayjs` is re-exported for your convenience. This is useful when the component and action would not work for programmatic usage, like setting the document title.
The `dayjs` library is exported from this package for your convenience.

**Note**: the exported `dayjs` function already extends the [relativeTime plugin](https://day.js.org/docs/en/plugin/relative-time).

```svelte
<script>
import { dayjs } from "svelte-time";
let timestamp = "";
</script>
<button on:click={() => (document.title = dayjs().format("MMM DD, YYYY"))}>
Set title
<button on:click={() => (timestamp = dayjs().format("HH:mm:ss.SSSSSS"))}>
Update {timestamp}
</button>
```

Expand Down
2 changes: 1 addition & 1 deletion src/Time.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@
$: title = relative ? dayjs(timestamp).format(format) : undefined;
</script>

<time {...$$restProps} {title} datetime={timestamp}>
<time {title} {...$$restProps} datetime={timestamp}>
{formatted}
</time>
5 changes: 4 additions & 1 deletion src/svelte-time.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import type { Action } from "svelte/action";
import type { TimeProps } from "./Time.svelte";

export interface SvelteTimeOptions
extends Pick<TimeProps, "timestamp" | "format" | "relative" | "live"> {}
extends Pick<
TimeProps,
"timestamp" | "format" | "relative" | "live" | "title"
> {}

export const svelteTime: Action<
HTMLElement,
Expand Down
8 changes: 7 additions & 1 deletion src/svelte-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ export const svelteTime = (node, options = {}) => {
let formatted = dayjs(timestamp).format(format);

if (relative) {
node.setAttribute("title", formatted);
if ("title" in options) {
if (options.title !== undefined) {
node.setAttribute("title", options.title);
}
} else {
node.setAttribute("title", formatted);
}

if (live !== false) {
interval = setInterval(
Expand Down
27 changes: 27 additions & 0 deletions tests/SvelteTime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SvelteComponent, tick } from "svelte";
import { dayjs as dayjsExported } from "svelte-time";
import SvelteTime from "./SvelteTime.test.svelte";
import SvelteTimeLive from "./SvelteTimeLive.test.svelte";
import SvelteTimeCustomTitle from "./SvelteTimeCustomTitle.test.svelte";

describe("svelte-time", () => {
let instance: null | SvelteComponent = null;
Expand Down Expand Up @@ -172,6 +173,32 @@ describe("svelte-time", () => {
expect(actionRelativeLive.getAttribute("datetime")).toEqual(timestamp);
});

test("SvelteTimeCustomTitle.test.svelte", async () => {
const target = document.body;

instance = new SvelteTimeCustomTitle({
target,
});

const relativeLive = target.querySelector(
'[data-test="custom-title"]',
) as HTMLTimeElement;
const relativeLiveOmit = target.querySelector(
'[data-test="custom-title-omit"]',
) as HTMLTimeElement;
const actionRelativeLive = target.querySelector(
'[data-test="action-custom-title"]',
) as HTMLTimeElement;
const actionRelativeOmit = target.querySelector(
'[data-test="action-custom-title-omit"]',
) as HTMLTimeElement;

expect(relativeLiveOmit.title).toEqual("");
expect(relativeLive.title).toEqual("Custom title");
expect(actionRelativeLive.title).toEqual("Custom title");
expect(actionRelativeOmit.title).toEqual("");
});

test("exported dayjs", () => {
expect(dayjsExported().from(dayjsExported())).toEqual("a few seconds ago");
});
Expand Down
23 changes: 23 additions & 0 deletions tests/SvelteTimeCustomTitle.test.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts">
import Time, { svelteTime } from "svelte-time";
</script>

<Time data-test="custom-title" relative title="Custom title" />

<Time data-test="custom-title-omit" relative title={undefined} />

<time
data-test="action-custom-title"
use:svelteTime={{
title: "Custom title",
relative: true,
}}
/>

<time
data-test="action-custom-title-omit"
use:svelteTime={{
title: undefined,
relative: true,
}}
/>

0 comments on commit 72a02ce

Please sign in to comment.