diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js index feec0f25ac8823..2786bf6d791212 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js @@ -12,20 +12,28 @@ import { dateI18n, getDate, humanTimeDiff, getSettings } from '@wordpress/date'; import { store as coreStore } from '@wordpress/core-data'; import { useSelect } from '@wordpress/data'; +const DAY_IN_MILLISECONDS = 60 * 60 * 1000 * 24; + /** * Returns a button label for the revision. * - * @param {Object} revision A revision object. + * @param {string|number} id A revision object. + * @param {boolean} isLatest Whether the revision is the most current. + * @param {string} authorDisplayName Author name. + * @param {string} formattedModifiedDate Revision modified date formatted. * @return {string} Translated label. */ -function getRevisionLabel( revision ) { - const authorDisplayName = revision?.author?.name || __( 'User' ); - - if ( 'parent' === revision?.id ) { +function getRevisionLabel( + id, + isLatest, + authorDisplayName, + formattedModifiedDate +) { + if ( 'parent' === id ) { return __( 'Reset the styles to the theme defaults' ); } - if ( 'unsaved' === revision?.id ) { + if ( 'unsaved' === id ) { return sprintf( /* translators: %s author display name */ __( 'Unsaved changes by %s' ), @@ -33,23 +41,18 @@ function getRevisionLabel( revision ) { ); } - const formattedDate = dateI18n( - getSettings().formats.datetimeAbbreviated, - getDate( revision?.modified ) - ); - - return revision?.isLatest + return isLatest ? sprintf( /* translators: %1$s author display name, %2$s: revision creation date */ __( 'Changes saved by %1$s on %2$s (current)' ), authorDisplayName, - formattedDate + formattedModifiedDate ) : sprintf( /* translators: %1$s author display name, %2$s: revision creation date */ __( 'Changes saved by %1$s on %2$s' ), authorDisplayName, - formattedDate + formattedModifiedDate ); } @@ -65,10 +68,18 @@ function getRevisionLabel( revision ) { * @return {JSX.Element} The modal component. */ function RevisionsButtons( { userRevisions, selectedRevisionId, onChange } ) { - const currentTheme = useSelect( - ( select ) => select( coreStore ).getCurrentTheme(), - [] - ); + const { currentThemeName, currentUser } = useSelect( ( select ) => { + const { getCurrentTheme, getCurrentUser } = select( coreStore ); + const currentTheme = getCurrentTheme(); + return { + currentThemeName: + currentTheme?.name?.rendered || currentTheme?.stylesheet, + currentUser: getCurrentUser(), + }; + }, [] ); + const dateNowInMs = getDate().getTime(); + const { date: dateFormat, datetimeAbbreviated } = getSettings().formats; + return (
    { userRevisions.map( ( revision, index ) => { - const { id, author, modified } = revision; - const authorDisplayName = author?.name || __( 'User' ); - const authorAvatar = author?.avatar_urls?.[ '48' ]; - const isUnsaved = 'unsaved' === revision?.id; + const { id, isLatest, author, modified } = revision; + const isUnsaved = 'unsaved' === id; + // Unsaved changes are created by the current user. + const revisionAuthor = isUnsaved ? currentUser : author; + const authorDisplayName = revisionAuthor?.name || __( 'User' ); + const authorAvatar = revisionAuthor?.avatar_urls?.[ '48' ]; const isSelected = selectedRevisionId - ? selectedRevisionId === revision?.id + ? selectedRevisionId === id : index === 0; - const isReset = 'parent' === revision?.id; + const isReset = 'parent' === id; + const modifiedDate = getDate( modified ); + const displayDate = + modified && + dateNowInMs - modifiedDate.getTime() > DAY_IN_MILLISECONDS + ? dateI18n( dateFormat, modifiedDate ) + : humanTimeDiff( modified ); + const revisionLabel = getRevisionLabel( + id, + isLatest, + authorDisplayName, + dateI18n( datetimeAbbreviated, modifiedDate ) + ); return (
  1. { onChange( revision ); } } - label={ getRevisionLabel( revision ) } + label={ revisionLabel } > { isReset ? ( { __( 'Default styles' ) } - { currentTheme?.name?.rendered || - currentTheme?.stylesheet } + { currentThemeName } ) : ( - + { isUnsaved ? ( + + { __( '(Unsaved)' ) } + + ) : ( + + ) } - { isUnsaved - ? sprintf( - /* translators: %s author display name */ - __( - 'Unsaved changes by %s' - ), - authorDisplayName - ) - : sprintf( - /* translators: %s author display name */ - __( 'Changes saved by %s' ), - authorDisplayName - ) } - { + { authorDisplayName } ) } diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/style.scss b/packages/edit-site/src/components/global-styles/screen-revisions/style.scss index 238f3f7d116e19..6598fcb5ce1c74 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/style.scss +++ b/packages/edit-site/src/components/global-styles/screen-revisions/style.scss @@ -8,62 +8,80 @@ margin: 0; li { margin-bottom: 0; - border-left: 1px solid $gray-300; } } .edit-site-global-styles-screen-revisions__revision-item { position: relative; - padding: $grid-unit-10 0 $grid-unit-10 $grid-unit-15; + padding-left: $grid-unit-20; + overflow: hidden; + cursor: pointer; - &:first-child { - padding-top: 0; + &:hover { + background: rgba(var(--wp-admin-theme-color--rgb), 0.04); + .edit-site-global-styles-screen-revisions__date { + color: var(--wp-admin-theme-color); + } } - &:last-child { - padding-bottom: 0; + &::before, + &::after { + position: absolute; + content: "\a"; + display: block; } &::before { background: $gray-300; border-radius: 50%; - content: "\a"; - display: inline-block; height: $grid-unit-10; width: $grid-unit-10; - position: absolute; - top: 50%; - left: 0; + top: $grid-unit-20 + 2; + left: $grid-unit-20 + 1; // So the circle is centered on the line. transform: translate(-50%, -50%); + z-index: 1; } &.is-selected::before { background: var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); } -} -.edit-site-global-styles-screen-revisions__revision-button { - width: 100%; - height: auto; - display: block; - padding: $grid-unit-10 $grid-unit-15; + &::after { + height: 100%; + left: $grid-unit-20; + top: 0; + width: 0; + border: 0.5px solid $gray-300; + } - &:hover { - background: rgba(var(--wp-admin-theme-color--rgb), 0.04); + &:first-child::after { + top: $grid-unit-20 + 2; + } - .edit-site-global-styles-screen-revisions__date { - color: var(--wp-admin-theme-color); + &:last-child::after { + height: $grid-unit-20 + 2; + } + + // Nested to override specificity of .components-button. + .edit-site-global-styles-screen-revisions__revision-button { + width: 100%; + height: auto; + display: block; + padding: $grid-unit-15 $grid-unit-15 $grid-unit-15 $grid-unit-30; + &:focus, + &:active { + outline: 0; + box-shadow: none; } } } .is-selected { + color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); + background: rgba(var(--wp-admin-theme-color--rgb), 0.04); .edit-site-global-styles-screen-revisions__revision-button { - color: var(--wp-components-color-accent, var(--wp-admin-theme-color, #007cba)); opacity: 1; - background: rgba(var(--wp-admin-theme-color--rgb), 0.04); } - - .edit-site-global-styles-screen-revisions__meta { + .edit-site-global-styles-screen-revisions__date { color: var(--wp-admin-theme-color); } } @@ -78,20 +96,26 @@ flex-direction: column; align-items: flex-start; gap: $grid-unit-10; + .edit-site-global-styles-screen-revisions__date { + text-transform: uppercase; + font-weight: 600; + font-size: 12px; + } } .edit-site-global-styles-screen-revisions__meta { - color: $gray-700; + color: $gray-600; display: flex; - justify-content: space-between; + justify-content: start; width: 100%; align-items: center; - text-align: left; + font-size: 12px; img { width: $grid-unit-20; height: $grid-unit-20; border-radius: 100%; + margin-right: $grid-unit-10; } }