neos / neos-ui

Neos CMS UI written in ReactJS with Immutable data structures.
GNU General Public License v3.0
265 stars 135 forks source link

Allow custom styling of Collection ContentElementWrapping #3620

Open bwaidelich opened 6 years ago

bwaidelich commented 6 years ago

The rendering of (empty) ContentCollections is hard-coded in the Neos Backend: It renders the empty addEmptyContentCollectionOverlay-Div via JS that displays the grey 2px outline which is not changeable via custom CSS because of the dynamic class attribute from React.

In addition to a fixed class attribute it would be very handy to be able to set an "empty notice" from Fusion and/or further classes for custom styling per use case.

bwaidelich commented 6 years ago

In a customer project we achieved that using CSS variables:

# add "emptyNotice" property to ContentElementWrapping
prototype(Neos.Neos:ContentElementWrapping) {
    emptyNotice = ''
    @context.emptyNotice = ${this.emptyNotice}
    additionalAttributes {
        style = ${'--empty-notice: "' + emptyNotice + '"'}
        style.@if.hasEmptyNotice = ${!String.isBlank(emptyNotice)}
    }
}

and the corresponding CSS:

.neos-backend .neos-contentcollection[style] > div:empty:after {
  content: var(--empty-notice);
}

(if anyone has similar requirements)

bwaidelich commented 6 years ago

Related to that the overlay should be rendered for all collections IMO not only ContentCollections

Sebobo commented 6 years ago

I like the idea and think that would be helpful for editors. But wouldn't the overlay be confusing for for normal collections when they might not be interactive / selectable?

jonnitto commented 6 years ago

I solve this always like that:

// Improve a bit UX when there's no content at all
// and add an indication where to click to start.

@keyframes empty-collection-arrow {
  0%,
  25%,
  100% {
    transform: translateY(0);
  }

  5%,
  15% {
    transform: translateY(-4px);
  }

  10%,
  20% {
    transform: translateY(4px);
  }
}

.neos-contentcollection > [class^="style__addEmptyContentCollectionOverlay"] {
  cursor: pointer;
  height: $height;
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;

  &::before,
  &::after {
    display: inline-block;
    color: #adadad;
    opacity: 0.5;
    transition: opacity 0.2s ease;
    line-height: 41px;
  }

  &::after {
    margin: 0 1rem;
    content: "\21e7";
    animation: empty-collection-arrow 2.5s infinite 2s;
  }

  &::before {
    content: "Click here to add content";
  }

  &:hover {
    &::before,
    &::after {
      opacity: 1;
    }
  }
}
bwaidelich commented 6 years ago

But wouldn't the overlay be confusing for for normal collections when they might not be interactive / selectable?

Yes, it should only be added for those that are

[class^="style__addEmptyContentCollectionOverlay"]

Haha, clever work around for the addressing issue. But I don't know how safe it is to rely on the internal creation of class names in React. I hope that we can use Web Components at some point, so this could be

neos-empty-content-collection-overlay {
  // ...
}
jonnitto commented 5 years ago

@bwaidelich Could you implement something like a CSS class neos-contentcollection--empty to have a proper way to address empty content collections?

bwaidelich commented 5 years ago

@jonnitto untested but this could work

prototype(Neos.Neos:ContentCollection) {
    attributes.class.@process.emptyCollectionClass = ${value + ' neos-contentcollection--empty'}
    attributes.class.@process.emptyCollectionClass.@if.isEmpty = ${q(node).children().count() == 0}
}

But it would not be updated when you remove the last child unless you refresh the browser..

bwaidelich commented 5 years ago

..if you suggested to add this class to the dynamically added overlay - that's exactly what this ticket suggests :)