Problem/Motivation

Child of #3617065: Expected components constraints for slots. #3544026: Cardinality constraints for slots enforces maxItems, but nothing in the Builder or the Scaffold tells the user. A full slot just refuses the drop, without saying why, and a click insert from the library lands one level up, #3628802: Insert from the library without dragging. The user learns that a slot takes one element only when it refuses the second.

minItems and expected will add more rules the user cannot see.

Proposed resolution

Show each constraint where the slot is drawn, before the user acts:

  • maxItems: the slot label gets the count, "Content 1/1", and a full slot looks full.
  • While dragging, a dropzone that refuses the dragged element, full or not expected, looks closed instead of refusing silently.
  • minItems: a slot under its minimum says so in its label, as a warning, not an error: SDC only suggests.
  • expected: the slot says what it accepts, on hover.

Where:

  • Builder: the slot label, from data-slot-title, shown while dragging or with the Highlight slot toggle.
  • Scaffold: the slot card header.
  • Navigator: the slot row.
  • Assistive tech: the same words in the slot's accessible name, with #3624637: Plan: Builder accessibility and UX.

The server already stamps data-max-items on each dropzone. The count and the other constraints join it as attributes, so CSS and the drag share one source.

Remaining tasks

User interface changes

Slots show their limits and what they accept, and look closed when they cannot take more.

API changes

None.

Data model changes

None.

CommentFileSizeAuthor
#16 builder-scaffold.jpg148.4 KBjuc1
#16 db-slots-items.jpg147.78 KBjuc1
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mogtofu33 created an issue. See original summary.

mogtofu33’s picture

pdureau’s picture

pdureau’s picture

Issue tags: -AI-accelerated, -D8UX usability +UX
pdureau’s picture

Issue tags: +Novice

I put "Novice" tag because the difficult part of this ticket is not the implementation, but the UI/UX proposal. It is also a way of welcoming proposal from occasional contributors.

wkr1shna’s picture

Hi! I'd like to contribute to this issue, starting with the `maxItems` part.

My initial proposal is to show the current count in the slot label (for example, `Content 1/1`), visually distinguish full slots, and indicate during dragging when a dropzone cannot accept another item. I'd aim to keep the feedback consistent across the Canvas, Scaffold, and Navigator, while making sure the slot's accessible name communicates the same constraint.

I'll first inspect the existing `data-max-items` handling and the relevant UI components to see how best to implement this without duplicating state.

Does this direction fit what you had in mind? I'm happy to refine the UI proposal before starting the implementation.

pdureau’s picture

Hi Krishna,

Thanks for you interest on this topic.

My initial proposal is to show the current count in the slot label (for example, `Content 1/1`), visually distinguish full slots, and indicate during dragging when a dropzone cannot accept another item.

That an interesting proposal.

However, the information we want to convey is broader than a slot having max items and being full or not. The main information is "can i add something to a slot?

We have isDropzoneLocked(element) in dropzone.js which is only wrapping isDropzoneFull(element) for now, but there will be other mechanisms "locking" the dropzone (#3551232: Add a lock system, #3617065: Expected components constraints for slots...).

If you can add such count (for example, `Content 1/1`), that's cool, but it must not be added against a more generic and reusable visual clue.

I'd aim to keep the feedback consistent across the Canvas, Scaffold, and Navigator, while making sure the slot's accessible name communicates the same constraint.

Sounds nice.

Be careful: this ticket is only about displaying information, not about mechanisms preventing adding something to a slot, which has been done in #3627023: Duplicate is offered where it can only fail: a full root or slot

You are welcomed to assign the ticket to you :)

wkr1shna’s picture

Assigned: Unassigned » wkr1shna

Thanks for the clarification! I understand the distinction now: the primary visual clue should communicate whether a slot can accept content, regardless of why the dropzone is locked. The item count can be supplementary information, but it shouldn't be the mechanism users rely on to understand whether adding content is possible.

I'll keep this issue focused on displaying the existing dropzone state, without changing the logic that prevents additions. I'll inspect how `isDropzoneLocked(element)` and the existing dropzone attributes are exposed to the Canvas, Scaffold, and Navigator, then propose a consistent visual treatment before implementing it.

I'll assign the issue to myself as suggested.

pdureau’s picture

Title: Show slot constraints in the Canvas and the Scaffold » Show slot constraints in the Builder and the Scaffold
Issue summary: View changes

exposed to the Canvas, Scaffold, and Navigator

"Canvas" is now called "Builder"

wkr1shna’s picture

Status: Active » Needs review
juc1’s picture

I am doing a UX review, will report results later today...

pdureau’s picture

Hi @juc1, please assign to tou if you are doing review.

@wkr1shna is still assigned but has finished they work, so I believe it is OK to switch.

wkr1shna’s picture

Assigned: wkr1shna » Unassigned

Thanks for the update! I'm happy for @juc1 to take over the issue for the UX review. The implementation is pushed to MR !524, and I'm available to address any feedback or follow-up changes that come out of the review.

juc1’s picture

Assigned: Unassigned » juc1
juc1’s picture

StatusFileSize
new147.78 KB
new148.4 KB

UX review of MR !524 using \tests\modules\display_builder_test\components\test_slot_constraints with
slot title "Slot with 2 items max".

The MR gives very helpful visual information about slot capacity and locked status. A few suggestions:

  1. Add brackets to delineate the count from the SDC name:
    Currently (without MR): Slot with 2 items max
    With this MR: Slot with 2 items max 2/2
    Suggestion: Slot with 2 items max (2/2) or Slot with 2 items max (2/2 items used)
    (Brackets help separate the component author's label from the system metadata, especially when the slot name ends in a number or word like "max").
  2. Add a hover tooltip to the slot title on constrained slots:
    For slots with maxItems, a hover tooltip on the slot title would clarify the status for users, for example:
    "2 / 2 items used - this slot is full and cannot accept more items"
  3. Padlock SVG:
    The current inline SVG padlock shape is not clear in my browser - suggestion: change the SVG to the official Bootstrap Icons lock-fill https://icons.getbootstrap.com/icons/lock-fill/ and perhaps make it slightly larger (such as 0.875rem instead of the current 0.75rem).
  4. Builder badge width & truncation:
    @pdureau Even without this MR, slot titles get truncated in the Builder view due to:
    /* components/dropzone/dropzone.css:135-140 */
        .db-dropzone[data-slot-title]::before {
          position: absolute;
          top: 0;
          left: 0;
          max-width: var(--dropzone-label-max-width); /* 10rem (160px) */
          white-space: nowrap;
          text-overflow: ellipsis;
        }

    Because the count is appended to the end, the new constraint count gets swallowed by the ellipsis (e.g.
    🔒 Slot with 2 items m...). Notice that in Scaffold view it does not truncate (second screenshot below).

    Allowing a bit more width specifically for constrained slots fixes this without changing the global 10rem token:

    .db-dropzone[data-slot-title][data-slot-count]::before {
          max-width: 14rem; /* or min(15rem, 50%) so it never reaches the right corner */
        }

Item count works correctly:

slots

Truncation in Builder view:

builder

juc1’s picture

Assigned: juc1 » Unassigned