diff --git a/.changeset/lucky-gifts-tie.md b/.changeset/lucky-gifts-tie.md new file mode 100644 index 0000000000..bd12fef029 --- /dev/null +++ b/.changeset/lucky-gifts-tie.md @@ -0,0 +1,26 @@ +--- +"@patternfly/elements": major +--- + +✨ Added `` replacing ``. Timestamp now follows +PatternFly v6 design specs. + +```html + + +``` + +**Breaking Changes from v5** + +- `` → `` +- `import '@patternfly/elements/pf-v5-timestamp/pf-v5-timestamp.js'` → + `import '@patternfly/elements/pf-v6-timestamp/pf-v6-timestamp.js'` +- CSS custom properties `--_timestamp-*` → `--pf-v6-c-timestamp--*` + +**New features** + +- ✨ `help-text` boolean attribute for tooltip trigger styling with keyboard focus +- ✨ Default slot for custom display content +- ✨ v6 design tokens diff --git a/docs/main.mjs b/docs/main.mjs index 2664df6bb8..cb235fa5f9 100644 --- a/docs/main.mjs +++ b/docs/main.mjs @@ -32,7 +32,7 @@ import '@patternfly/elements/pf-v5-tabs/pf-v5-tabs.js'; import '@patternfly/elements/pf-v5-text-area/pf-v5-text-area.js'; import '@patternfly/elements/pf-v5-text-input/pf-v5-text-input.js'; import '@patternfly/elements/pf-v5-tile/pf-v5-tile.js'; -import '@patternfly/elements/pf-v5-timestamp/pf-v5-timestamp.js'; +import '@patternfly/elements/pf-v6-timestamp/pf-v6-timestamp.js'; import '@patternfly/elements/pf-v5-tooltip/pf-v5-tooltip.js'; // if `/v2/` path load icons from static directory diff --git a/elements/pf-v5-timestamp/README.md b/elements/pf-v5-timestamp/README.md deleted file mode 100644 index 1e39721e09..0000000000 --- a/elements/pf-v5-timestamp/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# PatternFly Elements Timestamp - -A timestamp provides consistent formats for displaying date and time values. - -Read more about Datetime in the [PatternFly Elements Timestamp documentation](https://patternflyelements.org/components/timestamp) - -## Installation - -Load `` via CDN: - -```html - -``` - -Or, if you are using [NPM](https://npm.im), install it - -```bash -npm install @patternfly/elements -``` - -Then once installed, import it to your application: - -```js -import '@patternfly/elements/pf-v5-timestamp/pf-v5-timestamp.js'; -``` - -## Usage - -### Just the date: January 2, 2006 -```html - - -``` - -### With time: Monday, January 2, 2006 at 3:04:05 PM EST -```html - - -``` - -### With an en-GB locale: Monday, 2 January 2006 at 15:04:05 GMT-5 -You can use any locale here. -```html - - -``` - -### Relative time: 17 years ago -```html - - -``` - diff --git a/elements/pf-v5-timestamp/demo/basic-formats.html b/elements/pf-v5-timestamp/demo/basic-formats.html deleted file mode 100644 index 8486314b15..0000000000 --- a/elements/pf-v5-timestamp/demo/basic-formats.html +++ /dev/null @@ -1,17 +0,0 @@ -
-

-

-

-

-

-
- - - - diff --git a/elements/pf-v5-timestamp/demo/custom-format.html b/elements/pf-v5-timestamp/demo/custom-format.html deleted file mode 100644 index 094a64fc00..0000000000 --- a/elements/pf-v5-timestamp/demo/custom-format.html +++ /dev/null @@ -1,23 +0,0 @@ -
-

- - -
- - - - diff --git a/elements/pf-v5-timestamp/demo/custom-tooltip.html b/elements/pf-v5-timestamp/demo/custom-tooltip.html deleted file mode 100644 index 8cb5b91417..0000000000 --- a/elements/pf-v5-timestamp/demo/custom-tooltip.html +++ /dev/null @@ -1,25 +0,0 @@ -
-

- - - Last updated on - -

-

- - Halloween - - -

-
- - - - diff --git a/elements/pf-v5-timestamp/demo/index.html b/elements/pf-v5-timestamp/demo/index.html deleted file mode 100644 index 1b50e9d610..0000000000 --- a/elements/pf-v5-timestamp/demo/index.html +++ /dev/null @@ -1,13 +0,0 @@ -
-

-
- - - - diff --git a/elements/pf-v5-timestamp/demo/relative-format-with-tooltip.html b/elements/pf-v5-timestamp/demo/relative-format-with-tooltip.html deleted file mode 100644 index a74706684f..0000000000 --- a/elements/pf-v5-timestamp/demo/relative-format-with-tooltip.html +++ /dev/null @@ -1,25 +0,0 @@ -
-

- - - - -

-

- - - - -

-
- - - - diff --git a/elements/pf-v5-timestamp/demo/relative-format.html b/elements/pf-v5-timestamp/demo/relative-format.html deleted file mode 100644 index 9f6e90d2d6..0000000000 --- a/elements/pf-v5-timestamp/demo/relative-format.html +++ /dev/null @@ -1,18 +0,0 @@ -
-

-

-

-

-

-

-
- - - - diff --git a/elements/pf-v5-timestamp/demo/tooltip.html b/elements/pf-v5-timestamp/demo/tooltip.html deleted file mode 100644 index 4f692c36aa..0000000000 --- a/elements/pf-v5-timestamp/demo/tooltip.html +++ /dev/null @@ -1,25 +0,0 @@ -
-

- - - - -

-

- - - - -

-
- - - - diff --git a/elements/pf-v5-timestamp/docs/CHANGELOG.old.md b/elements/pf-v5-timestamp/docs/CHANGELOG.old.md deleted file mode 100644 index 468dd61ee6..0000000000 --- a/elements/pf-v5-timestamp/docs/CHANGELOG.old.md +++ /dev/null @@ -1,57 +0,0 @@ -# @patternfly/pfe-timestamp - -## 2.0.0-next.5 - -### Minor Changes - -- daba8a53: Changing from pfe-datetime to pfe-timestamp - -## 2.0.0-next.4 - -### Patch Changes - -- bfad8b4b: Updates dependencies -- Updated dependencies [bfad8b4b] - - @patternfly/pfe-core@2.0.0-next.8 - -## 2.0.0-next.3 - -### Patch Changes - -- 6a2a0407: [View commit message here](https://gist.github.com/heyMP/200fc0b840690541475923facba393ab) -- Updated dependencies [6a2a0407] - - @patternfly/pfe-core@2.0.0-next.4 - -## 2.0.0-next.2 - -### Patch Changes - -- 447b2d75: Remove `esbuild` export condition, as this anyways was a runtime error -- Updated dependencies [447b2d75] - - @patternfly/pfe-core@2.0.0-next.3 - -## 2.0.0-next.1 - -### Patch Changes - -- 1e89269b: document `time-zone-name` attribute - -## 2.0.0-next.0 - -### Major Changes - -- 48e48655: ## 🔥 Migrate to Lit - - This release migrates `` to LitElement. - - ### Breaking Changes - - - Initial render is now [asynchronous](https://lit.dev/docs/components/lifecycle/#reactive-update-cycle). - If your code assumes that shadow DOM is ready once the element is constructed, update it to `await element.updateComplete` - - See [docs](https://patternflyelements.org/components/datetime/) for more info - -### Patch Changes - -- Updated dependencies [e8788c72] - - @patternfly/pfe-core@2.0.0-next.0 diff --git a/elements/pf-v5-timestamp/docs/pf-v5-timestamp.md b/elements/pf-v5-timestamp/docs/pf-v5-timestamp.md deleted file mode 100644 index ea081ec503..0000000000 --- a/elements/pf-v5-timestamp/docs/pf-v5-timestamp.md +++ /dev/null @@ -1,139 +0,0 @@ -{% renderInstallation %} {% endrenderInstallation %} - -{% renderOverview %} - A timestamp provides consistent formats for displaying date and time values. - - Default: - - With a locale of es: - - Relative time: -{% endrenderOverview %} - -{% band header="Usage" %} - ### Default - By default, a timestamp will display the current date and time based on the current locale if the date attribute is not set. - - {% htmlexample %} - - {% endhtmlexample %} - - ### Basic formats - The format of the displayed content can be customized by setting the `date-format` and/or `time-format` attributes. Setting only one of the attributes will display only the date or time, depending on which attribute is set. The possible options are "full", "long", "medium", and "short". - - You can also set the `display-suffix` attribute to display a custom suffix at the end of the displayed content. This will not override a timezone that is already displayed from the applied time format. - - {% htmlexample %} - - {% endhtmlexample %} - - {% htmlexample %} - - {% endhtmlexample %} - - {% htmlexample %} - - {% endhtmlexample %} - - {% htmlexample %} - - - {% endhtmlexample %} - - ### Custom format - The format of the displayed content can be further customized by setting the custom-format attributes. Read [datetime format options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options) for a list of options that can be set. - - {% htmlexample %} - - - {% endhtmlexample %} - - ### Adding a tooltip - To add a tooltip that displays the timestamp content as a UTC time, you can wrap `pf-v5-timestamp` with `pf-v5-tooltip` and set the `utc` attribute on an additional `pf-v5-timestamp`. - - {% htmlexample %} - - - - - {% endhtmlexample %} - - {% htmlexample %} - - - - - {% endhtmlexample %} - - ### Relative time - To display relative time, set the `relative` attribute on `pf-v5-timestamp`. - - {% htmlexample %} - - {% endhtmlexample %} - - {% htmlexample %} - - {% endhtmlexample %} - - ### Relative time with a tooltip - To display relative time, set the `relative` attribute on `pf-v5-timestamp`. - - {% htmlexample %} - - - - - {% endhtmlexample %} - - {% htmlexample %} - - - - - {% endhtmlexample %} - - ### Set a locale to something other than the default locale - The default locale is inferred by the browser. To set the locale to something else, set the `locale` attribute. - - {% htmlexample %} - - {% endhtmlexample %} - - {% htmlexample %} - - {% endhtmlexample %} - - ### As a UTC timestamp - Set the `utc` attribute. - - {% htmlexample %} - - {% endhtmlexample %} -{% endband %} - -{% renderSlots %}{% endrenderSlots %} - -{% renderAttributes %}{% endrenderAttributes %} - -{% renderProperties %}{% endrenderProperties %} - -{% renderMethods %}{% endrenderMethods %} - -{% renderEvents %}{% endrenderEvents %} - -{% renderCssCustomProperties %}{% endrenderCssCustomProperties %} - -{% renderCssParts %}{% endrenderCssParts %} diff --git a/elements/pf-v5-timestamp/docs/screenshot.png b/elements/pf-v5-timestamp/docs/screenshot.png deleted file mode 100644 index 07767332a1..0000000000 Binary files a/elements/pf-v5-timestamp/docs/screenshot.png and /dev/null differ diff --git a/elements/pf-v5-timestamp/pf-v5-timestamp.css b/elements/pf-v5-timestamp/pf-v5-timestamp.css deleted file mode 100644 index 91def3703c..0000000000 --- a/elements/pf-v5-timestamp/pf-v5-timestamp.css +++ /dev/null @@ -1,8 +0,0 @@ -:host { - display: inline; -} - -time { - text-decoration: var(--_timestamp-text-decoration, none); - text-underline-offset: var(--_timestamp-text-underline-offset, initial); -} diff --git a/elements/pf-v5-timestamp/pf-v5-timestamp.ts b/elements/pf-v5-timestamp/pf-v5-timestamp.ts deleted file mode 100644 index 040e9fec6f..0000000000 --- a/elements/pf-v5-timestamp/pf-v5-timestamp.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { ComplexAttributeConverter, PropertyValues, TemplateResult } from 'lit'; - -import { LitElement, html } from 'lit'; -import { customElement } from 'lit/decorators/custom-element.js'; -import { property } from 'lit/decorators/property.js'; - -import { - TimestampController, - type DateTimeFormat, -} from '@patternfly/pfe-core/controllers/timestamp-controller.js'; - -import style from './pf-v5-timestamp.css'; - -const BooleanStringConverter: ComplexAttributeConverter = { - fromAttribute(value) { - return !value || value === 'true'; - }, -}; - -/** - * A **timestamp** provides consistent formats for displaying date and time values. - * @alias Timestamp - */ -@customElement('pf-v5-timestamp') -export class PfV5Timestamp extends LitElement { - static readonly styles: CSSStyleSheet[] = [style]; - - @property({ reflect: true, attribute: 'date-format' }) dateFormat?: DateTimeFormat; - - @property({ reflect: true, attribute: 'time-format' }) timeFormat?: DateTimeFormat; - - @property({ attribute: false }) customFormat?: object; - - @property({ reflect: true, attribute: 'display-suffix' }) displaySuffix?: string; - - @property({ reflect: true }) locale?: string; - - @property({ reflect: true, type: Boolean }) relative?: boolean; - - @property({ reflect: true, type: Boolean }) utc?: boolean; - - @property({ - reflect: true, - attribute: 'hour-12', - converter: BooleanStringConverter, - }) hour12?: boolean; - - @property({ reflect: true }) - get date(): string { - return this.#timestamp.localeString; - } - - set date(string) { - this.#timestamp.date = new Date(string); - } - - get isoString(): string { - return this.#timestamp.isoString; - } - - get time(): string { - return this.#timestamp.time; - } - - #timestamp = new TimestampController(this); - - connectedCallback(): void { - super.connectedCallback(); - if (this.hasAttribute('date')) { - this.#timestamp.date = new Date(this.getAttribute('date')!); - } - } - - willUpdate(changedProperties: PropertyValues): void { - for (const [prop] of changedProperties) { - this.#timestamp.set(prop, this[prop as keyof this]); - } - } - - render(): TemplateResult<1> { - return html` - - `; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'pf-v5-timestamp': PfV5Timestamp; - } -} diff --git a/elements/pf-v5-timestamp/test/pf-timestamp.spec.ts b/elements/pf-v5-timestamp/test/pf-timestamp.spec.ts deleted file mode 100644 index 6155fd4d09..0000000000 --- a/elements/pf-v5-timestamp/test/pf-timestamp.spec.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { expect, html } from '@open-wc/testing'; -import { createFixture } from '@patternfly/pfe-tools/test/create-fixture.js'; -import { PfV5Timestamp } from '@patternfly/elements/pf-v5-timestamp/pf-v5-timestamp.js'; - -describe('', function() { - it('imperatively instantiates', function() { - expect(document.createElement('pf-v5-timestamp')).to.be.an.instanceof(PfV5Timestamp); - }); - - it('should upgrade', async function() { - const element = await createFixture(html``); - expect(element, 'the should be an instance of PfV5Timestamp') - .to.be.an.instanceof(customElements.get('pf-v5-timestamp')) - .and - .to.be.an.instanceof(PfV5Timestamp); - }); - - it('should show the current date by default with default formatting', async function() { - const element = await createFixture(html` - - `); - - const expected = new Date().toLocaleString(); - - expect(element.time).to.equal(expected); - }); - - it('should set the correct ISO date on the datetime attribute in the time element', async function() { - const date = new Date('Sat Jan 01 2022 00:00:00'); - const dateString = date.toString(); - const expected = date.toISOString(); - const element = await createFixture(html` - - `); - - expect(element.isoString).to.equal(expected); - }); - - it('should show a passed in date with default formatting', async function() { - const dateString = 'Sat Jan 01 2022 00:00:00'; - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(new Date(dateString).toLocaleString()); - }); - - it('should show custom formatting when date-format and time-format are passed in', async function() { - const dateString = 'Sat Jan 01 2022 00:00:00'; - const expected = new Date(dateString).toLocaleString('en-US', { dateStyle: 'full', timeStyle: 'short' }); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show only a date when date-format is passed in', async function() { - const dateString = 'Sat Jan 01 2022 00:00:00'; - const expected = new Date(dateString).toLocaleString('en-US', { dateStyle: 'full' }); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show only time when time-format is passed in', async function() { - const dateString = 'Sat Jan 01 2022 00:00:00'; - const expected = new Date(dateString).toLocaleString('en-US', { timeStyle: 'short' }); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show custom formatting when customFormat is passed in', async function() { - const dateString = 'Sat Jan 01 2022 00:00:00'; - const options: Intl.DateTimeFormatOptions = { - year: '2-digit', - month: 'short', - weekday: 'short', - day: 'numeric', - hour: 'numeric', - }; - const expected = new Date(dateString).toLocaleString('en-US', options); - const element = await createFixture(html` - - `); - expect(element.time).to.equal(expected); - }); - - it('should show a custom suffix when display-suffix is passed in', async function() { - const dateString = 'Sat Jan 01 2022 00:00:00'; - const suffix = 'US Eastern'; - const expected = `${new Date(dateString).toLocaleString('en-US')} ${suffix}`; - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show a 12 hour time', async function() { - const dateString = 'Sat Jan 01 2022 13:00:00'; - const expected = new Date(dateString).toLocaleString('en-US'); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show a 24 hour time when hour-12 is set to false', async function() { - const dateString = 'Sat Jan 01 2022 13:00:00'; - const expected = new Date(dateString).toLocaleString('en-US', { hour12: false }); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show with locale passed in', async function() { - const date = new Date(2022, 1, 1).toString(); - const expected = new Date(date).toLocaleString('en-GB'); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show a 12 hour time by default for US locale', async function() { - const date = new Date(2022, 1, 1, 13, 0).toString(); - const expected = new Date(date).toLocaleString('en-US'); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show a 24 hour time for US locale when hour-12 is false', async function() { - const date = new Date(2022, 1, 1, 13, 0).toString(); - const expected = new Date(date).toLocaleString('en-US', { hour12: false }); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show a 12 hour time for a 24 hour locale when hour-12 is passed', async function() { - const date = new Date(2022, 1, 1, 13, 0).toString(); - const expected = new Date(date).toLocaleString('en-GB', { hour12: true }); - const element = await createFixture(html` - - `); - - expect(element.time).to.equal(expected); - }); - - it('should show relative time of the moment', async function() { - const date = new Date(); - const element = await createFixture(html` - - `); - - expect(element.time).to.match(/just now/); - }); - - it('should show relative time in the past', async function() { - const date = new Date(2015, 7, 9, 14, 57, 0); - const element = await createFixture(html` - - `); - - expect(element.time).to.match(/\d+ years ago/); - }); - - it('should show relative time in the future', async function() { - const date = new Date(2099, 7, 9, 14, 57, 0); - const element = await createFixture(html` - - `); - - expect(element.time).to.match(/in \d+ years/); - }); -}); diff --git a/elements/pf-v6-timestamp/README.md b/elements/pf-v6-timestamp/README.md new file mode 100644 index 0000000000..88770cfc53 --- /dev/null +++ b/elements/pf-v6-timestamp/README.md @@ -0,0 +1,56 @@ +# pf-v6-timestamp + +A timestamp provides consistent formats for displaying date and time values. + +## Usage + +### Basic date and time + +```html + + +``` + +### Relative time + +```html + + +``` + +### With tooltip (UTC display) + +```html + + + + +``` + +## Divergences from React `Timestamp` + +### Not implemented + +| React prop | Notes | +|---|---| +| `tooltip` | Use composition with `` wrapping the timestamp instead. The web component pattern favors slot-based composition over configuration objects. | + +### Changed API + +| React prop | Web component | Difference | +|---|---|---| +| `is12Hour` | `hour-12` attribute | Renamed to dash-case per HTML convention. Supports `hour-12="false"` for explicit 24-hour. | +| `shouldDisplayUTC` | `utc` attribute | Shorter, idiomatic HTML attribute name. Functionally equivalent. | +| `date` (Date object) | `date` attribute (string) | Accepts any string parseable by `new Date()` rather than a Date object, since HTML attributes are strings. | +| `customFormat` (prop) | `.customFormat` property | Set via JavaScript property only (not reflectable as attribute). | +| `tooltip.variant="default"` | `help-text` + composition | Dashed underline from `help-text` attr; tooltip via `` wrapping. | +| `children` | Default slot | Slotted content replaces computed display, matching web component conventions. | + +### Added + +| Web component API | Notes | +|---|---| +| `help-text` attribute | Boolean attribute that applies the dashed-underline "help text" styling from the v6 design system, indicating a tooltip is available. | +| Default slot | Slot for custom display content (e.g. relative time text). The `datetime` attribute on the inner `