Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sticky Position: Try re-enabling non-root sticky position #49321

Merged
merged 10 commits into from
Jun 16, 2023
36 changes: 24 additions & 12 deletions packages/block-editor/src/hooks/position.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { addFilter } from '@wordpress/hooks';
import BlockList from '../components/block-list';
import useSetting from '../components/use-setting';
import InspectorControls from '../components/inspector-controls';
import useBlockDisplayInformation from '../components/use-block-display-information';
import { cleanEmptyObject } from './utils';
import { unlock } from '../lock-unlock';
import { store as blockEditorStore } from '../store';
Expand Down Expand Up @@ -222,32 +223,39 @@ export function PositionPanel( props ) {
const allowSticky = hasStickyPositionSupport( blockName );
const value = style?.position?.type;

const { hasParents } = useSelect(
const { firstParentClientId } = useSelect(
( select ) => {
const { getBlockParents } = select( blockEditorStore );
const parents = getBlockParents( clientId );
return {
hasParents: parents.length,
};
return { firstParentClientId: parents[ parents.length - 1 ] };
},
[ clientId ]
);

const blockInformation = useBlockDisplayInformation( firstParentClientId );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Crazy idea: could we use this client id to instead inject a style in the DOM like #block-clientid :has(.ist-sticky.is-selected) { outline: 1px solid grey} or whatever?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that is a clever idea — I can't remember why exactly, but I think from memory there was a preference to try to use popovers so that we don't accidentally collide with any styles that a theme might have for a particular block. It could be to ensure that the visualizers / popover always displays its CSS styling in addition to whatever might be set on the parent block (that we can't quite know) rather than overriding anything. Worth playing with though!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I picked outline because it's very unlikely that it gets used for block styling, as it's mostly a property applied on focus. Though if the popover calculations are performant I suppose it's not really an issue.

const stickyHelpText =
allowSticky && value === STICKY_OPTION.value && blockInformation
? sprintf(
/* translators: %s: the name of the parent block. */
__(
'The block will stick to the scrollable area of the parent %s block.'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, just asking:

Is there a way to tell if a block is nested inside a template?

I know getting sticky to work on templates is off the cards for now, but I guess folks might try to make the header sticky and until we can get that working this doesn't make much sense when I try to make Header > Group sticky:

The block will stick to the scrollable area of the parent Header block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to tell if a block is nested inside a template?

Good question!

Unfortunately it's a tricky one to figure out, because depending on what a user's site layout is like, there could be a good case for a user making their block sticky to the immediate parent within a header. I suppose it's one of the challenges of exposing the controls in non-root positions — we'd like to try to help communicate what's going to happen, but at the same time, it's up to users to use the tools however it suits their current designs 🤔

Personally, I'd probably explore tweaking logic surrounding where the block sits in relation to templates / template parts in follow-ups, as it gets quite tricky to come up with something the feels just right.

Thanks for taking a look!

),
blockInformation.title
)
: null;

const options = useMemo( () => {
const availableOptions = [ DEFAULT_OPTION ];
// Only display sticky option if the block has no parents (is at the root of the document),
// or if the block already has a sticky position value set.
if (
( allowSticky && ! hasParents ) ||
value === STICKY_OPTION.value
) {
// Display options if they are allowed, or if a block already has a valid value set.
// This allows for a block to be switched off from a position type that is not allowed.
if ( allowSticky || value === STICKY_OPTION.value ) {
availableOptions.push( STICKY_OPTION );
}
if ( allowFixed || value === FIXED_OPTION.value ) {
availableOptions.push( FIXED_OPTION );
}
return availableOptions;
}, [ allowFixed, allowSticky, hasParents, value ] );
}, [ allowFixed, allowSticky, value ] );

const onChangeType = ( next ) => {
// For now, use a hard-coded `0px` value for the position.
Expand Down Expand Up @@ -281,7 +289,11 @@ export function PositionPanel( props ) {
web:
options.length > 1 ? (
<InspectorControls group="position">
<BaseControl className="block-editor-hooks__position-selection">
<BaseControl
className="block-editor-hooks__position-selection"
__nextHasNoMarginBottom
help={ stickyHelpText }
>
<CustomSelectControl
__nextUnconstrainedWidth
__next36pxDefaultSize
Expand Down