| @@ -1,24 +1,65 @@ | ||
| 1 | +import { useState } from '@wordpress/element'; | |
| 1 | 2 | import { Icon } from '@wordpress/icons'; |
| 3 | +import classNames from 'classnames'; | |
| 4 | +import { bannerButtonVariables, buttonHoverClasses, colorsOf } from '../colors'; | |
| 2 | 5 | import { iconFor } from '../icons'; |
| 3 | 6 | import { externalLinkProps } from '../notification-link'; |
| 7 | +import { publishAndReload, publishesSite } from '../publish-site'; | |
| 4 | 8 | |
| 5 | 9 | export const Pill = ({ notification, href, external, onClick }) => { |
| 6 | 10 | const ctaLabel = notification['cta-label']; |
| 7 | 11 | const icon = iconFor(notification.icon); |
| 12 | + const colors = colorsOf(notification); | |
| 13 | + const [publishing, setPublishing] = useState(false); | |
| 14 | + const publishes = publishesSite(notification); | |
| 15 | + // Core's admin bar is taller below the md breakpoint; the pill matches it. | |
| 16 | + const className = classNames( | |
| 17 | + 'inline-flex h-7.5 shrink-0 items-center gap-1 rounded-sm bg-banner-main px-2.5 text-sm leading-none text-banner-text no-underline md:h-6 md:text-[13px]', | |
| 18 | + publishing ? 'cursor-not-allowed' : 'cursor-pointer', | |
| 19 | + !publishing && buttonHoverClasses(colors), | |
| 20 | + ); | |
| 21 | + // The pill has no room for a spinner, so the reload is the only feedback. | |
| 22 | + const publishNow = () => { | |
| 23 | + setPublishing(true); | |
| 24 | + publishAndReload(onClick); | |
| 25 | + }; | |
| 8 | 26 | |
| 27 | + const shared = { | |
| 28 | + // Without this the pill has no accessible name where CSS hides the label. | |
| 29 | + 'aria-label': ctaLabel, | |
| 30 | + className, | |
| 31 | + style: bannerButtonVariables(colors), | |
| 32 | + 'data-test': 'notification-pill', | |
| 33 | + }; | |
| 34 | + const label = ( | |
| 35 | + <> | |
| 36 | + {icon && <Icon icon={icon} size={16} className="fill-current" />} | |
| 37 | + <span className="ext-notification-pill-label">{ctaLabel}</span> | |
| 38 | + </> | |
| 39 | + ); | |
| 40 | + | |
| 41 | + if (publishes) { | |
| 42 | + return ( | |
| 43 | + <button | |
| 44 | + type="button" | |
| 45 | + onClick={publishNow} | |
| 46 | + disabled={publishing} | |
| 47 | + aria-busy={publishing} | |
| 48 | + {...shared} | |
| 49 | + > | |
| 50 | + {label} | |
| 51 | + </button> | |
| 52 | + ); | |
| 53 | + } | |
| 54 | + | |
| 9 | 55 | return ( |
| 10 | 56 | <a |
| 11 | 57 | href={href} |
| 12 | 58 | {...externalLinkProps(external)} |
| 13 | 59 | onClick={onClick} |
| 14 | - // Without this the pill has no accessible name where CSS hides the label. | |
| 15 | - aria-label={ctaLabel} | |
| 16 | - // Core's admin bar is taller below the md breakpoint; the pill matches it. | |
| 17 | - className="inline-flex h-7.5 shrink-0 cursor-pointer items-center gap-1 rounded-sm bg-banner-main px-2.5 text-sm leading-none text-banner-text no-underline hover:opacity-90 md:h-6 md:text-[13px]" | |
| 18 | - data-test="notification-pill" | |
| 60 | + {...shared} | |
| 19 | 61 | > |
| 20 | - {icon && <Icon icon={icon} size={16} className="fill-current" />} | |
| 21 | - <span className="ext-notification-pill-label">{ctaLabel}</span> | |
| 62 | + {label} | |
| 22 | 63 | </a> |
| 23 | 64 | ); |
| 24 | 65 | }; |