PluginProbe
Extendify / 3.1.5
Extendify v3.1.5
3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 0.7.0 All 126 releases
extendify / src / QuickEdit / components / toolbar / HeadingLevelButton.jsx

HeadingLevelButton.jsx in Extendify 3.1.5, at src/QuickEdit/components/toolbar/HeadingLevelButton.jsx

82 lines 2.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { Button, Popover } from '@wordpress/components';
2 import { useDispatch, useSelect } from '@wordpress/data';
3 import { useRef, useState } from '@wordpress/element';
4 import { __, sprintf } from '@wordpress/i18n';
5
6 const LEVELS = [1, 2, 3, 4, 5, 6];
7
8 // Gutenberg ships the heading-level picker inside `.block-editor-block-switcher`,
9 // which our floating bar hides (transform options aren't in scope for QE).
10 // Restore just the level picker as a standalone button, matching the
11 // ColorButton shape so the bar feels uniform.
12 export function HeadingLevelButton() {
13 const [open, setOpen] = useState(false);
14 const wrapRef = useRef(null);
15
16 const selected = useSelect((select) => {
17 const editor = select('core/block-editor');
18 const clientId = editor.getSelectedBlockClientId();
19 if (!clientId) return null;
20 const block = editor.getBlock(clientId);
21 if (!block || block.name !== 'core/heading') return null;
22 return { clientId, level: Number(block.attributes?.level) || 2 };
23 }, []);
24
25 const dispatch = useDispatch('core/block-editor');
26
27 if (!selected) return null;
28
29 const setLevel = (level) => {
30 dispatch?.updateBlockAttributes?.(selected.clientId, { level });
31 setOpen(false);
32 };
33
34 return (
35 <div className="relative inline-flex items-center" ref={wrapRef}>
36 <Button
37 className="extendify-quick-edit-heading-level-button"
38 label={__('Heading level', 'extendify-local')}
39 aria-expanded={open}
40 onMouseDown={(ev) => ev.preventDefault()}
41 onClick={() => setOpen((v) => !v)}
42 >
43 <span aria-hidden="true">{`H${selected.level}`}</span>
44 </Button>
45 {open ? (
46 <Popover
47 placement="bottom-start"
48 onClose={() => setOpen(false)}
49 focusOnMount="firstElement"
50 className="extendify-quick-edit extendify-quick-edit-heading-level-popover"
51 anchor={wrapRef.current}
52 >
53 <div
54 className="extendify-quick-edit-heading-level-popover-inner"
55 role="listbox"
56 aria-label={__('Heading level', 'extendify-local')}
57 >
58 {LEVELS.map((n) => (
59 <Button
60 key={n}
61 role="option"
62 aria-selected={selected.level === n}
63 className="extendify-quick-edit-heading-level-option"
64 variant={selected.level === n ? 'primary' : 'tertiary'}
65 onClick={() => setLevel(n)}
66 onMouseDown={(ev) => ev.preventDefault()}
67 label={sprintf(
68 // translators: %d is the heading level number 1-6.
69 __('Heading %d', 'extendify-local'),
70 n,
71 )}
72 >
73 {`H${n}`}
74 </Button>
75 ))}
76 </div>
77 </Popover>
78 ) : null}
79 </div>
80 );
81 }
82