Our previous post highlighted the new capabilities of the venerable FileMaker button. In FileMaker 12’s Design Surface, the once-humble button gains new-found expressive power, enabling it to respond fluidly to user hovers, taps, and clicks via what we termed interactive formatting. The catch: interactive buttons — whether in FileMaker 12, or on any other platform — are prone to semantic misinformation, in which interactive formatting unintentionally misleads and confuses users.
In this post, we’ll learn two lightweight techniques that will give full control of button appearance and behavior. With these two new tools in hand, we’ll be able to fully — and easily — meet the semantic challenge, and create better, more intuitive solutions.
Before getting started, we invite you to download the companion demo file: ButtonUp2.fmp12. This file provides a (sort of) real world demonstration of the challenge of semantic misinformation, and illustrates the solutions we’ll present in this post.
The Challenge: In the demo file, elements of a bottom button set independently change their availability as business rules act on live data. The first tab demonstrates how standard buttons offer no clues to their availability, forcing users to rely on mere trial and error. Here, a user learns that William Shatner, while spiffily attired, lacks the right stuff to provide secret decoder rings.
Whenever we want to add state-aware behavior to interactively formatted buttons, the tool we’ll reach for is conditional formatting. FileMaker developers have long trusted this tool to provide real time visual feedback informing users of the state (condition) of data. Now, with the advent of FileMaker 12’s Design Surface, conditional formatting becomes the perfect complement to interactive formatting. Used in concert, these two formatting tools will let us create interactive, state-aware buttons that remain semantically meaningful as data changes.
Let’s begin with a basic approach, a technique we’ll call a conditional overlay:
- With a button selected, let’s open Conditional Formatting and add a rule that will evaluate to True when we want our button to be disabled. For a “delete” button, our rule might evaluate to true when the current record’s status is anything other than “draft”, while for an “OK” button in a modal dialog layout, our rule might evaluate to true until all required fields have valid values. Since conditional formatting rules evaluate from top to bottom; we’ll place our state-aware rule last, to ensure button-disabling rules always take precedence.
- Assign a solid conditional fill color (and optionally text color) that will communicate a state of unavailability to users when our button is closed for business.
- Last, add this same conditional check to the button’s code, so that the script linked to this button will also silently exit when our conditions are met. (In production, this test should be abstracted so that script and formatting rely on a single test. This might be an unstored calculated field, a script-triggered global variable, or perhaps best of all, a custom function, as we use in our companion demo file).
Tools of the Trade: Applying a conditional fill is straightforward, particularly if we first set up a lightweight custom function to do any heavy lifting required, say, by one Bullwinkle J. Moose.
To Tell the Truth
Here’s what we get for our efforts: When our disabling conditional rule evaluates to False (when our button is active) conditional formatting will have no effect, and our button will be unchanged. But now, when our conditional rule evaluates to True (when our button is inactive), conditional formatting will spring into effect, and our button will assume the “inactive” appearance defined in our conditional rule.
Having our button be visibly inactive in normal state is a good start. But here’s the crucial bit: Our button’s interactive behavior will also fundamentally change. When it’s in effect, conditional formatting will effectively “turn off” our button’s interactive formatting, preventing it from visually responding to user actions. Users can hover, click, tap, or even tickle our buttons to their hearts’ content: As long as our disabling condition evaluates to True, our noble button will now stand as rigidly still as a highly trained royal guard. Minus the funny hat.
This gives us the ability to toggle at will between visually dynamic, active buttons and static, inactive objects. When one of our buttons is open for business, its interactive formatting will clearly advertise this to our users; when it’s closed, our conditional override will now clearly signal its inactive state to users. We’ve met our semantic button challenge. The enhancements we learn in the rest of this post will be further feathers in our buttons’ already finely festooned fedoras. Huzzah!
Success! Thanks to the Conditional Overlay, users immediately know that Fearless Leader can in fact receive evil-grams or supply us with a coveted decoder ring, but that other functions are off limits to this nefarious villain.
The Mighty Cascade
Our first technique works because conditional formatting rules supersede interactive formatting. This is what makes it possible for us to “turn off” our button’s interactive formatting. Let’s take a quick step back to see how and why this happens:
Design Surface is built on Cascading Style Sheet (CSS) technology. The heart of CSS is the cascade, an elegant and compact specification determining how object formatting (styles) will flow predictably from abstract, generalized rules to the most detailed object- and state-specific level. CSS is designed to anticipate — and in fact encourage — conflict at different levels of the cascade. This architecture allows us to apply general styles with a broad brush, and then hone in on specific objects as desired. CSS adjudicates conflicts using a simple test: the rule applied at the most specific level of the cascade always wins.
CSS’s ability to assemble formatting rules applied at different levels and economically resolve conflicts between these rules is the basis of its elegance and power. Whether on the web in general, or in Design Surface specifically, best practice is to apply a lean set of “inexpensive” formatting rules at the most generalized level possible, then override these general settings on specific objects and states (where rules are more “expensive”) only as needed.
Each specific implementation of a cascade has a specific hierarchy that determines its behavior. The Design Surface cascade looks like this:
Map of the Territory: The Design Surface cascade gives us an essential master view of how objects will behave and interact throughout our solutions.
Through the Looking Glass
With that under our belts, let’s try a quick pop quiz:
“FileMaker 12 conditional formatting can now assign transparent fills. What will happen when a conditional rule that ‘fills’ a button with a completely transparent color (RBGa 100%,100%,100%,0) evaluates to True?”
(a) The button’s appearance won’t change. The transparent conditional fill will allow upstream fill properties to cascade through unaffected.
(b) The button will become transparent. The transparent conditional fill will effectively “erase” upstream fill properties, completely removing them.
(c) There’s a “pop” who now?
Scanning the virtual room, pretty much everyone chose (a) — except that kid in the corner who keeps mumbling to himself in proto Klingon. No surprise, really. Common sense tells us that a transparent layer will simply allow whatever’s behind it flow through, like laying clear glass over another object. Group hug, high fives all around, and… ruh roh… the correct answer is (b).
Why? It turns out that our young Trekkie simply applied the foundation principle of the cascade: In the cascade, when rules governing the same property conflict with each other, the more specific rule always wins outright. So if we conditionally apply a transparent fill, its CSS fill attributes (specifically, its background-image and background-color properties) will completely replace all upstream values, whether they be solid fills, gradients, or images. As a result, a transparent conditional fill will indeed act as an “eraser”, leaving an object truly transparent.
Less is More
The ability of conditionally-applied formatting to completely override upstream styles opens a door to our second technique, the “conditional clear“. Here, we apply conditional rules just as before, this time assigning transparent fills when our conditional tests evaluate to True.
What does this give us? For starters, conditionally cleared objects can completely disappear from our interfaces on demand, and this is very useful indeed. In practice, it’s often preferable to completely remove these objects when they’re not available to users. Some examples: Portal row delete buttons; Search field clear buttons; Action buttons not available to users of certain privilege sets. In cases like these, less is often more, both aesthetically and semantically.
The conditional clear also opens further doors to richer design possibilities. For example, we can use it to effectively “scratch off” a button to reveal objects hidden beneath it. As another example, we can apply a partially transparent conditional fill. Interestingly, unlike in our earlier example, this semi-transparent fill will visually interact with the objects behind it (since they’re separate objects and not part of the same object cascade).
A final bonus: Conditional clears are more maintainable than their conditional overlay cousins. If we change a layout’s theme or copy buttons across layouts, objects using conditional fills may need to be updated one by one. In contrast, the conditional clear by definition is at home in any theme, be it dark, light, or filled with gradients or rich images.
I Can See Clearly Now: The conditional clear allows buttons simply to vanish when inactive. Our users now confidently send the ever-hip Austin Powers their groovy-grams, never missing the ability to send him an email or evil-gram, since these buttons are completely hidden.
One More Thing
The conditional overlay and conditional clear provide the needed tools to successfully meet the semantic challenge posed in our previous Button. Up. blog post. We can now readily create and maintain buttons that communicate clearly and transparently, and our solutions and apps will be the better for it.
But the best is yet to come. In our next series post, we’ll step things up another notch and take these techniques beyond the button, creating complex and expressive native design patterns like state-aware toggle switches, progress bars, and status indicators.