Discussion - Custom Attribute Behaviors

Hi everyone! Kory and I wanted to get you thoughts on an idea we are considering involving custom attributes. For context, if you’ve used the “Add to Cart Button” element before you’ll notice it’s just a button but has some Custom Attributes preconfigured for you to be compliant with WooCommerce markup.

After Pro 4 (Loopers, Element Conditions, and Effects), we’ve found that so much can be done by simply composing a few core elements together. In fact, you can probably use the Div + Text elements to create just about any kind of static content (e.g. no javascript).

What if you just wanted to add a predictable behavior to any element? Here are a few quick examples:

  • Turn any button into an Add to Cart Button without having to change elements.
  • Wait 5s before showing an element
  • Close the closest Toggleable area
  • Other custom triggers for element toggles
  • Automatically open a modal when the page loads or on exit intent

Many of these come from thinking of future potential of offscreen content (more discussion on that topic here).

Try it yourself

Here’s a quick example to get a feel for it:

  1. Add this Custom CSS
[data-delay-fade]:not([data-delay-fade-complete]) {
  opacity: 0;
  pointer-events: none;
}
  1. Add this Custom JS
window.csGlobal.everinit('[data-delay-fade]', function(el) {
  el.getAttribute('data-delay-fade')
  setTimeout(function() {
    el.setAttribute('data-delay-fade-complete', true)
  }, el.getAttribute('data-delay-fade'))
});
  1. Add a Button, then go to Custom Attributes and add a new attribute with data-delay-fade as the name and 5000 as the value.

You should see the element fade in after 5 seconds.


We’re thinking this feature would be a new button next to Custom Attributes that opened a little modal that was similar to Dynamic Content. When you select a behavior it automatically adds all the custom attributes you need. All the JS and CSS would already be in Pro/Cornerstone. The biggest downside is those particular behaviors would be less approachable than adding actual controls to all elements. To change them, you’d have to directly manipulate the custom attributes.


We’re curious on your overall take on the idea, and also if there are any other use cases that come to mind.

2 Likes

Here’s one more example that’s is very experimental: Custom Toggleable areas. @devinelston you brought this up recently and it’s been on my mind. It’s been slippery to approach because you have to pair unique IDs across elements somehow. We don’t have a way to do this automatically, and it would be a good amount of time to build a system for that.

But, it might be something we could just make possible using Custom Attributes instead of having to make new elements. I wouldn’t advise using it in production because it uses non public APIs that might have breaking changes, but you can actually get something working doing this:

  • Add a Button with these custom attributes
    • data-x-toggle = custom-area
    • data-x-toggleable = custom-area
  • Add a Row with this custom attributes
    • data-x-toggleable = custom-area

Notice that when you click the button, both the button and the row get an x-active class.

3 Likes

All those sound great!

I don’t mind having them as Custom attributes at all, but I imagine many users would love them more as controls. Then again, so many controls are overwhelming, and this is much more expandable.

Oh, one more thing: the “Add to cart button” is actually compliant only for archives and pages. It is not compliant for product pages. In case of a product page, it should have the single_add_to_cart_button class. Perhaps this was intentional because the “Add to cart form” is needed on the Product page anyway.

Also, This button is getting triggered in the Builders, reloading the content inside. It would be great to stop that behavior. I keep forgetting it and messing the work up. :slight_smile:

An additional use case. I wanted to create a store directory where the functionality was similar to the Layered Navigation element. For example, have a list of store names in a list – but when the user clicks one, a pane slides in with contact details, etc. I spent a little while trying to figure out how to achieve this using the same attributes and classes as the Layered Nav elements, but wasn’t able to get it quite right…

Also, yeah, the tabs like we’ve talked about would be awesome.

Another is triggering an off-canvas element using other buttons or text. I figured out how to do this already, but I’ve been waiting for this release to go back through a site and make this change across the site. The specific use case for mine is having info in a modal, and wanting to give users several ways to get to that modal… without using the #link or duplicating the modal a bunch of times.

@Misho thanks! I’ll check on that cart button issue.

@devinelston, I’m still working through some issues with nested elements, but having nested Off Canvas elements would definitely be a step closer to what you’re talking about. Instead of using Layered Nav directly you could just keep adding Off Canvas elements inside each other that will reveal deeper layers. The panels should just stack on top of each other. The only issue presently is that the close button will close them all. So having something I mentioned earlier where we can only close the closest toggle would allow for a faux “back” button to be created using a normal Button element.

1 Like

Maybe it could be a user option to turn those controls on/off?

Maybe it could be a user option to turn those controls on/off?

That could be done by leaving them out of Advanced mode, but I’d actually like to start seeing as much consistency as possible with controls rather than having more bifurcation in what is present/hidden. Now that we have the on/off toggles, we will most likely remove “Advanced Mode” as a preference and just always show the full set of controls.

Hey everyone,

I wanted to bump this thread to mention that we’re using Sliders as somewhat of a proving ground for this concept. There will be a Slider “Element” but also ways to interact with the slider externally. For example, in these screenshots we have some ad-hoc slider controls composed of Divs, Buttons, and a Text element. These are just the existing elements you’re already using, but with a few custom attributes applied to link the slider functionality.

Screen Shot 2021-09-02 at 6.32.36 PM
Screen Shot 2021-09-02 at 6.31.54 PM

They can exist somewhere else on the page, but still target a slider. The 5/10 Text Element content is powered by a special variant of Dynamic Content that will update in real time. It looks like this (API/naming subject to change):

{{dc:rivet:slider key="page"}} / {{dc:rivet:slider key="pages"}}

Which creates this HTML on the front end:

<span data-tco-rivet="slider.page">1</span> / <span data-tco-rivet="slider.pages">10</span>

And in javascript land, everything is synced up so the text updates as you navigate the slider.


These systems are what will eventually power the “toggleable areas” feature that will let you make your own elements behave like Tabs. I’m not sure if that will land this cycle, but we’ll definitely have some of the underlying systems/requirements built out. Looking forward to sharing more with you all later in the month.

4 Likes

I’m super excited about that :raised_hands:

BTW, is that little bar above the buttons a visual indicator of the slide timing? (One that grows like a little progress indicator? :face_with_monocle:)

1 Like

Yes! So that’s setup by…

  • using a Div with a background and fixed with to make a little line.
  • Next adding data-tco-slider-progress to an element. When present, it will automatically check how far the slider has progressed and add a style lie --tco-slider-progress: 0.5 to the element.
  • In Effects, we use var(--tco-slider-progress) in a Scale X Transform.
  • The combination of the above allows the line to scale horizontally to match the current progress in realtime.

A few lines of javascript baked into Cornerstone keeps the --tco-slider-progress up to date. Then we can quickly build out the rest in the builder itself. Instead of adding more “core elements”, we’re going to be leaning into these patterns more. The drawback is that it won’t be obvious to most users on how to customize it, but we’ve got some ideas on solving that as well with the Theme Options cycle.

5 Likes
  • Add a Button with these custom attributes
    • data-x-toggle = custom-area
    • data-x-toggleable = custom-area
  • Add a Row with this custom attributes
    • data-x-toggleable = custom-area

I’m playing around with this and added a “continue shopping” button to the bottom of an off canvas cart which, when clicked, closes the off-canvas. Seems to work ok.
I notice that for the button itself it’s appearance is always on the “interaction” setting. Is this because it is “active” since it is within the element it is trying to control/affect?

Hi @spedney, yes, if used with a button it will get an active style when the toggleable area is open.

A quick word on the topic as a whole, unfortunately we won’t have fully functional “toggleable areas” with this release. Behind the scenes we’re building out something that will likely be called the Rivet API. We’re using the core functionality heavily for Sliders, and once this release is out we’ll be in a good place to wire everything up to a data attribute driven API that will let you do just about everything discussed in this thread so far. I have working proof of concepts for:

  • Performing actions on timers
  • Custom tabs
  • Custom “Scroll Top” anchors
  • Tapping into “Scroll Effects” but instead of on scrolling, enabling/disabling them based on interacting with other elements
  • Keyboard shortcuts
  • Doing something on exit intent
  • Setting up a scroll interpolation CSS custom property. This can be used inside of a effects to transform elements based on the current scroll position (motion based parallax)

And more… Unfortunately it’s just not polished enough to work out for this cycle, but we have quite the foundation ready for doing front end state/event management and enriching the existing element library. I’m really looking forward to sharing more with you on that down the road.

2 Likes

Thanks for your response Alexander
Those things sound really exciting… Especially the last one – scroll interpolation.
There’s lots to look forward to :slight_smile:

We’re pretty excited about it for sure!

@alexander exciting stuff indeed!

I’d like to get back to the idea in the first post of this tread. I am sure you are too busy right now, but that new button next to custom attributes sounds fantastic.

Also, your delayed fade-in example is great. It would be fantastic if another attribute was added to control the fade-in duration. :slight_smile:

1 Like

I’m excited about getting back to it as well. Lots of possibilities. At this point we essentially have a framework for adding arbitrary “events”, “actions”, and “observers” to any element. Events will listen for things to happen like interactions, and trigger a corresponding action. An Action could be all kinds of behaviors, including updating internal variables. Observers will watch for variables that change, and update the DOM by way of classnames or CSS custom properties. A big part of the project will be making all the little behaviors and documenting it all which we didn’t want to do at this stage and hold up the slider release. We’ll be getting back to it before or alongside Theme Options reboot.

1 Like