Skip to content

Commit 89d5a0f

Browse files
authored
Add initial explainer for snap-to-activate. (#63)
1 parent f85319a commit 89d5a0f

File tree

1 file changed

+227
-0
lines changed

1 file changed

+227
-0
lines changed

snap-to-activate-explainer.md

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
2+
We'd like to make it easier and more reliable for developers to build user experiences
3+
where navigation can be done by moving parts of the UI
4+
in a way that can correspond to scrolling and then scroll snapping.
5+
This navigation should, in some cases, be able to change the URL,
6+
so that the resulting state can be linked to and shared.
7+
8+
## Use cases
9+
10+
Let's start by examining some use cases that this feature should address,
11+
and thus make it simpler for developers to address these use cases well and declaratively.
12+
13+
### Panels or carousel within a single page app
14+
15+
One use case is a set of panels or a carousel within a single page app,
16+
where swiping left or right moves to the adjacent panel
17+
(and typically each panel fills the entire width of the UI).
18+
It should be possible for navigating between panels to declaratively
19+
change the document URL (without a new document load, like `pushState`)
20+
to reflect the currently selected panel.
21+
In many cases there are also either buttons/tabs at the top or bottom,
22+
or arrows at the sides,
23+
to move between these panels.
24+
25+
(This use case can also integrate with patching
26+
and thus with lazy loading of the resources
27+
needed for each panel.
28+
This integration can work particularly well
29+
because a browser can start preloading content
30+
at the beginning of a gesture
31+
if that gesture might lead to a snap that activates and loads content.)
32+
33+
This use case is somewhat simpler since the activation here
34+
is intended to be nondestructive.
35+
(It does potentially cause resource loading,
36+
but that's normal for exploring additional pieces of an app's UI.)
37+
38+
Here are two examples taken from native Android apps:
39+
40+
> [!NOTE]
41+
> (INCLUDE VIDEO HERE from https://photos.app.goo.gl/9YonAy8GKg7vyQ1P6)
42+
>
43+
> In this case, the Android Photos app allows swiping from side to side
44+
> to navigate between photos.
45+
> If this were on the Web,
46+
> it would be expected for the URL to change
47+
> when the UI moves to a different photo.
48+
> This allows the URL of a single photo to be shared.
49+
50+
> [!NOTE]
51+
> (INCLUDE VIDEO HERE from https://photos.app.goo.gl/1ABe699gY39oiZmH9)
52+
>
53+
> In this case, the maps app allows similar swiping from side-to-side
54+
> to navigate between successive trains departing from a single subway station
55+
> in the same direction.
56+
> The trains can also be selected by tapping on the train departure time
57+
> at the top of the UI.
58+
> In this particular case URLs are probably less critical
59+
> since the information in this particular UI is extremely transient,
60+
> but in general this sort of UI may want to have shareable URLs to represent each item.
61+
62+
</div>
63+
64+
### Pull to refresh
65+
66+
A slightly more advanced use case is pull-to-refresh.
67+
This is a common UI pattern where scrolling a scrollable area
68+
(often but not always a list)
69+
to the top
70+
and then continuing to scroll a little bit past the top
71+
(where the scrolling goes slower than the user's finger
72+
to provide the feeling of resistance or pulling)
73+
causes the content to reload or to add new conent.
74+
This requires having UI in the overscroll area (the area past the end)
75+
of a scrollable container.
76+
When activated, the UI in the overscroll area can trigger the refresh.
77+
78+
(This depends on a separate plan for rendering content in the overscroll area.)
79+
80+
In this use case,
81+
snapping to and thus activating
82+
an element that is in the overscroll area
83+
would trigger the refresh.
84+
85+
This use case requires more care because the operation is destructive.
86+
This means that this use case requires more careful consideration
87+
of the implications for accessibility issues,
88+
such as how it works with keyboard navigation,
89+
how it integrates with assistive technology,
90+
etc.
91+
92+
> [!NOTE]
93+
> (INCLUDE VIDEO HERE from https://photos.app.goo.gl/JFuVWaXqnroUjeMH7)
94+
>
95+
> In this case, the Web interface of X (formerly Twitter) uses pull-to-refresh
96+
> to load new content if any is available
97+
> (which in this case it is not).
98+
99+
### Swipe actions (like swipe to dismiss/delete)
100+
101+
Another use case that is similar in many ways to pull-to-refresh
102+
is swipe-to-dismiss or swipe-to-delete.
103+
Many user interfaces with dialogs or notifications
104+
allow dismissing that dialog or notification
105+
by swiping it to the side.
106+
Many user interfaces with lists of items that the user can delete
107+
(for example, lists of messages)
108+
allow swiping an individual item to the side to either delete an item
109+
or remove it from the particular list that it is in (for example, to archive it).
110+
111+
This has many of the same concerns as pull-to-refresh:
112+
it depends on interaction with the overscroll area,
113+
and it is a destructive (perhaps more destructive than pull-to-refresh)
114+
action that requires the same level care regarding accessibility issues.
115+
(Many of the issues appear to be the same,
116+
although some aspects may also be different.)
117+
118+
> [!NOTE]
119+
> (INCLUDE VIDEO HERE from https://photos.app.goo.gl/N7D5k5WaDDCeoDQ27)
120+
>
121+
> In this case, the Android Gmail app uses a swipe gesture to
122+
> remove a message from the list of messages being shown.
123+
124+
## Additional constraints
125+
126+
Some things worth thinking about when designing a solution for this are:
127+
128+
* An element, particularly one within a single-page app,
129+
may be activated in this way more than once in the lifetime of the page.
130+
(This implies that while integration
131+
with [declarative patching](patching-explainer.md) is useful,
132+
the integration shouldn't be so tight that a second activation is
133+
difficult or has poor developer ergonomics.)
134+
135+
* While in many cases the snapping involved will be
136+
`scroll-snap-type: mandatory`,
137+
the design should probably consider `scroll-snap-type: proximity` as well.
138+
139+
## Possible directions
140+
141+
When considering possible technical solutions to these problems,
142+
we have to consider what goes on the HTML side and what goes on the CSS side.
143+
Keeping appropriate parts of the solution in HTML is likely necessary
144+
(although not sufficient) for ensuring good accessibility of the result.
145+
146+
### Element ID activation
147+
148+
One simple possibility that would address only a subset of the use cases
149+
is adding a mechanism so that snapping to an element
150+
navigates so that the URL's fragment is the element's ID.
151+
This could be a very simple solution to a subset of the use cases.
152+
It seems like it might be problematic
153+
because there is no other way to perform the navigation,
154+
and thus the ability to navigate to that URL
155+
(and thus be able to share the URL, etc.)
156+
might not be discoverable or accessible to
157+
users using assistive technologies or alternative input methods.
158+
It's also not clear how this could eventually be tied into
159+
[routemaps](route-matching-explainer.md),
160+
[declarative patching](patching-explainer.md),
161+
or more advanced features.
162+
163+
### Snapping to an element that is activated
164+
165+
Another possibility is that the element being snapped to is an element that
166+
can be activated, such as a link or a button.
167+
Activating this element could then lead to
168+
[declarative patching](patching-explainer.md) that replaces the element
169+
(or its contents) with the expected content.
170+
171+
This approach seems problematic for three reasons.
172+
First, users who need to use methods other than swiping
173+
(for example, keyboard or assistive technology)
174+
might be unable to discover or activate the element.
175+
Second, it might be problematic (in a carousel type situation)
176+
for activations other than the first,
177+
since the declarative patching has already happened and the button or link
178+
might now be gone.
179+
Third, the developer ergonomics are rather weird
180+
and probably too tied to declarative patching.
181+
182+
### Connecting to button or link
183+
184+
Another possibility that seems like it might
185+
address a larger portion of the use cases (perhaps all, or perhaps not)
186+
is a mechanism that indicates that snapping to an element *S*
187+
activates a different (link or button) element *A*.
188+
This mechanism could be a new HTML attribute
189+
(that goes on the element *S*)
190+
referencing the ID of another element (the element *A*).
191+
The HTML attribute could have an IDL reflection that returns an element
192+
(like the existing IDL attributes
193+
`ariaActiveDescendantElement` and `popoverTargetElement`).
194+
195+
We've talked to developers who have taken this sort of approach
196+
in their own site-specific code,
197+
so it seems likely to be viable for at least some uses.
198+
199+
This approach may be problematic in cases where it doesn't make sense
200+
to link to a separate element that can be activated.
201+
However, this might be a good thing,
202+
since that seems like a sign of a design that is likely to be inaccessible.
203+
Further investigation is needed to determine whether
204+
there are significant use cases
205+
where this design wouldn't work
206+
and where the fact that it doesn't work
207+
isn't a sign of a significant accessibility issue.
208+
209+
That the element being activated would be a link or button
210+
(which would effectively go through its normal activation process)
211+
seems likely to mean that this approach would integrate well with
212+
other ongoing work like
213+
[routemaps](route-matching-explainer.md) and
214+
[declarative patching](patching-explainer.md).
215+
216+
There are still some interesting accessibility questions with this approach.
217+
In particular, given an approach where there's always an alternative way to do the same activation,
218+
it's not clear how desirable it is to expose the snap-to-activate concepts to assistive technology.
219+
Further, if we do want to expose them to assistive technology,
220+
we need to figure out an appropriate way to do that
221+
(that makes the right tradeoffs between producing good experiences
222+
for users of assistive technology
223+
in cases where developers do think about assistive technology users
224+
and test with assistive technology,
225+
and producing at least minimally acceptible experiences
226+
in the cases where developers don't do those things
227+
but do follow general best practices in their code).

0 commit comments

Comments
 (0)