| @@ -12,14 +12,11 @@ | ||
| 12 | 12 | */ |
| 13 | 13 | import { useCallback, useEffect, useRef, useState } from 'react'; |
| 14 | 14 | import { |
| 15 | 15 | Button, |
| 16 | - DropdownMenu, | |
| 17 | 16 | __experimentalHStack as HStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis |
| 18 | 17 | Icon, |
| 19 | 18 | KeyboardShortcuts, |
| 20 | - MenuGroup, | |
| 21 | - MenuItem, | |
| 22 | 19 | Modal, |
| 23 | 20 | Spinner, |
| 24 | 21 | Tooltip, |
| 25 | 22 | __experimentalVStack as VStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis |
| @@ -28,11 +25,12 @@ | ||
| 28 | 25 | import { useCopyToClipboard } from '@wordpress/compose'; |
| 29 | 26 | import { useDispatch } from '@wordpress/data'; |
| 30 | 27 | import { applyFilters } from '@wordpress/hooks'; |
| 31 | 28 | import { __, _n, sprintf } from '@wordpress/i18n'; |
| 32 | -import { arrowUp, blockTable, copy, download, info, moreVertical, pencil, settings, shortcode, siteLogo, trash } from '@wordpress/icons'; | |
| 29 | +import { arrowUp, blockTable, box, copySmall, download, info, moreVertical, settings, shortcode, siteLogo, trash } from '@wordpress/icons'; | |
| 33 | 30 | import { displayShortcut, shortcutAriaLabel } from '@wordpress/keycodes'; |
| 34 | 31 | import { store as noticesStore } from '@wordpress/notices'; |
| 32 | +import { Menu } from '@wordpress/ui'; | |
| 35 | 33 | |
| 36 | 34 | /** |
| 37 | 35 | * Internal dependencies. |
| 38 | 36 | */ |
| @@ -38,9 +36,9 @@ | ||
| 38 | 36 | */ |
| 39 | 37 | import { initializeReactComponentInPortal } from '../common/react-loader'; |
| 40 | 38 | import processAjaxRequest from '../common/ajax-request'; |
| 41 | 39 | import { Notifications } from '../common/notifications'; |
| 42 | -import { TablePressIcon, TablePressIconSimple } from '../../img/tablepress-icon'; | |
| 40 | +import { TablePressIconSimple } from '../../img/tablepress-icon'; | |
| 43 | 41 | |
| 44 | 42 | /** |
| 45 | 43 | * Saves the table changes to the server. |
| 46 | 44 | * |
| @@ -232,10 +230,10 @@ | ||
| 232 | 230 | ); |
| 233 | 231 | |
| 234 | 232 | return ( |
| 235 | 233 | <Modal |
| 236 | - size="medium" | |
| 237 | - icon={ <Icon icon={ TablePressIcon } size="36" style={ { display: 'flex', marginRight: '1rem' } } /> } | |
| 234 | + size="small" | |
| 235 | + icon={ <Icon icon={ trash } size="36" style={ { display: 'flex' } } /> } | |
| 238 | 236 | title={ title } |
| 239 | 237 | isDismissible={ false } |
| 240 | 238 | onKeyDown={ handleEnter } |
| 241 | 239 | onRequestClose={ closeConfirmDeleteModal } |
| @@ -299,77 +297,101 @@ | ||
| 299 | 297 | .sort( ( a, b ) => a.name.localeCompare( b.name ) ); |
| 300 | 298 | |
| 301 | 299 | return ( |
| 302 | 300 | <VStack> |
| 303 | - <HStack style={ { maxWidth: '1000px' } }> | |
| 301 | + <HStack className="tablepress-header-bar-wrapper"> | |
| 304 | 302 | <HStack alignment="left" spacing={ 3 } expanded={ false }> |
| 305 | 303 | { /* Left side: Quick Navigation, Table ID, Table name */ } |
| 306 | - <DropdownMenu | |
| 307 | - icon={ TablePressIconSimple } | |
| 308 | - label={ __( 'Quick navigation', 'tablepress' ) } | |
| 304 | + <Menu.Root | |
| 305 | + modal={ false } | |
| 309 | 306 | open={ screenData.quickNavigationDropdownIsOpen } |
| 310 | - onToggle={ ( newQuickNavigationDropdownIsOpen ) => updateScreenData( { quickNavigationDropdownIsOpen: newQuickNavigationDropdownIsOpen } ) } | |
| 311 | - toggleProps={ { | |
| 312 | - onDoubleClick: scrollToTop, /* Scroll to Top on Double-click. (Double-click will also close the dropdown.) */ | |
| 313 | - shortcut: { | |
| 314 | - ariaLabel: shortcutAriaLabel.primary( 'j' ), | |
| 315 | - display: displayShortcut.primary( 'j' ), | |
| 316 | - }, | |
| 317 | - } } | |
| 307 | + onOpenChange={ ( isOpen ) => updateScreenData( { quickNavigationDropdownIsOpen: isOpen } ) } | |
| 318 | 308 | > |
| 319 | - { ( { onClose: closeMenu } ) => ( | |
| 320 | - <> | |
| 321 | - <MenuGroup> | |
| 322 | - <MenuItem | |
| 323 | - icon={ arrowUp } | |
| 324 | - onClick={ () => { | |
| 325 | - scrollToTop(); | |
| 326 | - closeMenu(); | |
| 327 | - } } | |
| 328 | - > | |
| 329 | - { __( 'Scroll to Top', 'tablepress' ) } | |
| 330 | - </MenuItem> | |
| 331 | - </MenuGroup> | |
| 332 | - <MenuGroup label={ featureModules.length > 0 && __( 'Common', 'tablepress' ) }> | |
| 333 | - { | |
| 309 | + <Menu.Trigger | |
| 310 | + render={ | |
| 311 | + <Button | |
| 312 | + icon={ TablePressIconSimple } | |
| 313 | + label={ __( 'Quick navigation', 'tablepress' ) } | |
| 314 | + onDoubleClick={ () => scrollToTop() } /* Scroll to Top on Double-click. (Double-click will also close the dropdown.) */ | |
| 315 | + shortcut={ { | |
| 316 | + ariaLabel: shortcutAriaLabel.primary( 'j' ), | |
| 317 | + display: displayShortcut.primary( 'j' ), | |
| 318 | + } } | |
| 319 | + /> | |
| 320 | + } | |
| 321 | + /> | |
| 322 | + <Menu.Popup | |
| 323 | + positioner={ <Menu.Positioner sideOffset={ 12 } /> } // Increase the offset to not have the top border be right on top of the bottom border of the header bar. | |
| 324 | + style={ | |
| 325 | + // Allow the menu to be higher than the default, so that more feature modules fit. | |
| 326 | + featureModules.length > 0 && { | |
| 327 | + maxHeight: 'min(var(--available-height), 80dvh)', | |
| 328 | + } | |
| 329 | + } | |
| 330 | + > | |
| 331 | + <Menu.Item | |
| 332 | + prefix={ <Menu.PrefixIcon icon={ arrowUp } /> } | |
| 333 | + onClick={ () => scrollToTop() } | |
| 334 | + > | |
| 335 | + <Menu.ItemLabel> | |
| 336 | + { __( 'Scroll to Top', 'tablepress' ) } | |
| 337 | + </Menu.ItemLabel> | |
| 338 | + </Menu.Item> | |
| 339 | + <Menu.Separator /> | |
| 340 | + <Menu.Group> | |
| 341 | + { featureModules.length > 0 && ( | |
| 342 | + <Menu.GroupLabel> | |
| 343 | + { __( 'Common', 'tablepress' ) } | |
| 344 | + </Menu.GroupLabel> | |
| 345 | + ) } | |
| 346 | + { | |
| 334 | 347 | [ |
| 335 | 348 | { section: 'table-information', label: __( 'Table Information', 'tablepress' ), icon: info }, |
| 336 | 349 | { section: 'table-data', label: __( 'Table Content', 'tablepress' ), icon: blockTable }, |
| 337 | - { section: 'table-manipulation', label: __( 'Table Manipulation', 'tablepress' ), icon: pencil }, | |
| 338 | 350 | { section: 'table-options', label: __( 'Table Options', 'tablepress' ), icon: settings }, |
| 339 | 351 | { section: 'datatables-features', label: __( 'Table Features for Site Visitors', 'tablepress' ), icon: siteLogo }, |
| 340 | 352 | ].map( ( { section, label, icon } ) => ( |
| 341 | - <MenuItem | |
| 353 | + <Menu.Item | |
| 342 | 354 | key={ section } |
| 343 | - icon={ icon } | |
| 355 | + prefix={ <Menu.PrefixIcon icon={ icon } /> } | |
| 344 | 356 | onClick={ () => { |
| 345 | 357 | document.getElementById( `tablepress_edit-${section}` ).scrollIntoView( { behavior: 'smooth', block: 'start' } ); |
| 346 | - closeMenu(); | |
| 347 | 358 | } } |
| 348 | 359 | > |
| 349 | - { label } | |
| 350 | - </MenuItem> | |
| 360 | + <Menu.ItemLabel> | |
| 361 | + { label } | |
| 362 | + </Menu.ItemLabel> | |
| 363 | + </Menu.Item> | |
| 351 | 364 | ) ) |
| 352 | 365 | } |
| 353 | - </MenuGroup> | |
| 354 | - { featureModules.length > 0 && ( | |
| 355 | - <MenuGroup label={ __( 'Feature Modules', 'tablepress' ) }> | |
| 356 | - { featureModules.map( ( { module } ) => ( | |
| 357 | - <MenuItem | |
| 358 | - key={ module } | |
| 359 | - onClick={ () => { | |
| 360 | - document.getElementById( `tablepress_edit-${module}` ).scrollIntoView( { behavior: 'smooth', block: 'start' } ); | |
| 361 | - closeMenu(); | |
| 362 | - } } | |
| 363 | - > | |
| 364 | - { tp.modules[ module ].name } | |
| 365 | - </MenuItem> | |
| 366 | - ) ) } | |
| 367 | - </MenuGroup> | |
| 368 | - ) } | |
| 369 | - </> | |
| 370 | - ) } | |
| 371 | - </DropdownMenu> | |
| 366 | + </Menu.Group> | |
| 367 | + { | |
| 368 | + featureModules.length > 0 && ( | |
| 369 | + <> | |
| 370 | + <Menu.Separator /> | |
| 371 | + <Menu.Group> | |
| 372 | + <Menu.GroupLabel> | |
| 373 | + { __( 'Feature Modules', 'tablepress' ) } | |
| 374 | + </Menu.GroupLabel> | |
| 375 | + { featureModules.map( ( { module, name } ) => ( | |
| 376 | + <Menu.Item | |
| 377 | + key={ module } | |
| 378 | + prefix={ <Menu.PrefixIcon icon={ box } style={ { color: 'transparent' } } /> } // The icon is needed as a placeholder to align the labels. | |
| 379 | + onClick={ () => { | |
| 380 | + document.getElementById( `tablepress_edit-${module}` ).scrollIntoView( { behavior: 'smooth', block: 'start' } ); | |
| 381 | + } } | |
| 382 | + > | |
| 383 | + <Menu.ItemLabel> | |
| 384 | + { name } | |
| 385 | + </Menu.ItemLabel> | |
| 386 | + </Menu.Item> | |
| 387 | + ) ) } | |
| 388 | + </Menu.Group> | |
| 389 | + </> | |
| 390 | + ) | |
| 391 | + } | |
| 392 | + </Menu.Popup> | |
| 393 | + </Menu.Root> | |
| 372 | 394 | <span |
| 373 | 395 | className="tablepress-header-table-id" |
| 374 | 396 | style={ { flexShrink: 0 } }> |
| 375 | 397 | { sprintf( __( 'ID: %s', 'tablepress' ), tableMeta.id ) } |
| @@ -425,63 +447,72 @@ | ||
| 425 | 447 | disabled={ screenData.isSaving } |
| 426 | 448 | accessibleWhenDisabled={ true } |
| 427 | 449 | onClick={ () => saveTableChanges( { screenData, updateScreenData, tableOptions, tableMeta, updateTableMeta, noticeOperations, noticesStoreDispatch } ) } |
| 428 | 450 | /> |
| 429 | - <DropdownMenu | |
| 430 | - icon={ moreVertical } | |
| 431 | - label={ __( 'More actions', 'tablepress' ) } | |
| 432 | - > | |
| 433 | - { ( { onClose: closeMenu } ) => ( | |
| 434 | - <> | |
| 435 | - <MenuGroup> | |
| 436 | - <MenuItem | |
| 437 | - ref={ copyShortcodeButtonRef } | |
| 438 | - icon={ shortcode } | |
| 439 | - info={ shortcodeText } | |
| 440 | - onClick={ () => closeMenu() } | |
| 441 | - > | |
| 442 | - { __( 'Copy Shortcode', 'tablepress' ) } | |
| 443 | - </MenuItem> | |
| 444 | - </MenuGroup> | |
| 445 | - { ( tp.screenOptions.currentUserCanCopyTable || tp.screenOptions.currentUserCanExportTable ) && ( | |
| 446 | - <MenuGroup> | |
| 447 | - { tp.screenOptions.currentUserCanCopyTable && ( | |
| 448 | - <MenuItem | |
| 449 | - icon={ copy } | |
| 450 | - href={ screenData.copyUrl } | |
| 451 | - > | |
| 451 | + <Menu.Root modal={ false }> | |
| 452 | + <Menu.Trigger | |
| 453 | + render={ | |
| 454 | + <Button | |
| 455 | + icon={ moreVertical } | |
| 456 | + label={ __( 'More actions', 'tablepress' ) } | |
| 457 | + /> | |
| 458 | + } | |
| 459 | + /> | |
| 460 | + <Menu.Popup | |
| 461 | + positioner={ <Menu.Positioner sideOffset={ 12 } /> } // Increase the offset to not have the top border be right on top of the bottom border of the header bar. | |
| 462 | + > | |
| 463 | + <Menu.Item | |
| 464 | + ref={ copyShortcodeButtonRef } | |
| 465 | + prefix={ <Menu.PrefixIcon icon={ shortcode } /> } | |
| 466 | + > | |
| 467 | + <Menu.ItemLabel> | |
| 468 | + { __( 'Copy Shortcode', 'tablepress' ) } | |
| 469 | + </Menu.ItemLabel> | |
| 470 | + <Menu.ItemDescription> | |
| 471 | + { shortcodeText } | |
| 472 | + </Menu.ItemDescription> | |
| 473 | + </Menu.Item> | |
| 474 | + { ( tp.screenOptions.currentUserCanCopyTable || tp.screenOptions.currentUserCanExportTable ) && ( | |
| 475 | + <> | |
| 476 | + <Menu.Separator /> | |
| 477 | + { tp.screenOptions.currentUserCanCopyTable && ( | |
| 478 | + <Menu.LinkItem | |
| 479 | + prefix={ <Menu.PrefixIcon icon={ copySmall } /> } | |
| 480 | + href={ screenData.copyUrl } | |
| 481 | + > | |
| 482 | + <Menu.ItemLabel> | |
| 452 | 483 | { __( 'Copy Table', 'tablepress' ) } |
| 453 | - </MenuItem> | |
| 454 | - ) } | |
| 455 | - { tp.screenOptions.currentUserCanExportTable && ( | |
| 456 | - <MenuItem | |
| 457 | - icon={ download } | |
| 458 | - href={ screenData.exportUrl } | |
| 459 | - > | |
| 484 | + </Menu.ItemLabel> | |
| 485 | + </Menu.LinkItem> | |
| 486 | + ) } | |
| 487 | + { tp.screenOptions.currentUserCanExportTable && ( | |
| 488 | + <Menu.LinkItem | |
| 489 | + prefix={ <Menu.PrefixIcon icon={ download } /> } | |
| 490 | + href={ screenData.exportUrl } | |
| 491 | + > | |
| 492 | + <Menu.ItemLabel> | |
| 460 | 493 | { __( 'Export Table', 'tablepress' ) } |
| 461 | - </MenuItem> | |
| 462 | - ) } | |
| 463 | - </MenuGroup> | |
| 464 | - ) } | |
| 465 | - { tp.screenOptions.currentUserCanDeleteTable && ( | |
| 466 | - <MenuGroup> | |
| 467 | - <MenuItem | |
| 468 | - icon={ trash } | |
| 469 | - isDestructive={ true } | |
| 470 | - href={ screenData.deleteUrl } | |
| 471 | - onClick={ ( event ) => { | |
| 472 | - setConfirmDeleteModalIsOpen( true ); | |
| 473 | - event.preventDefault(); | |
| 474 | - closeMenu(); | |
| 475 | - } } | |
| 476 | - > | |
| 477 | - { __( 'Delete Table', 'tablepress' ) } | |
| 478 | - </MenuItem> | |
| 479 | - </MenuGroup> | |
| 480 | - ) } | |
| 481 | - </> | |
| 482 | - ) } | |
| 483 | - </DropdownMenu> | |
| 494 | + </Menu.ItemLabel> | |
| 495 | + </Menu.LinkItem> | |
| 496 | + ) } | |
| 497 | + </> | |
| 498 | + ) } | |
| 499 | + { tp.screenOptions.currentUserCanDeleteTable && ( | |
| 500 | + <> | |
| 501 | + <Menu.Separator /> | |
| 502 | + <Menu.Item | |
| 503 | + prefix={ <Menu.PrefixIcon icon={ trash } style={ { color: '#cc1818' } } /> } | |
| 504 | + onClick={ () => setConfirmDeleteModalIsOpen( true ) } | |
| 505 | + style={ { color: '#cc1818' } } | |
| 506 | + > | |
| 507 | + <Menu.ItemLabel> | |
| 508 | + { __( 'Delete table', 'tablepress' ) } | |
| 509 | + </Menu.ItemLabel> | |
| 510 | + </Menu.Item> | |
| 511 | + </> | |
| 512 | + ) } | |
| 513 | + </Menu.Popup> | |
| 514 | + </Menu.Root> | |
| 484 | 515 | </HStack> |
| 485 | 516 | </HStack> |
| 486 | 517 | { noticeUI } |
| 487 | 518 | { confirmDeleteModalIsOpen && ( |