Designing for Different Devices (Touch & Hover)

This document outlines the APIs used to adapt Discourse’s user interface for different devices.

Touch & Hover

Some devices only have touchscreens, some only have a traditional mouse pointer, and some have both. Importantly, touchscreen users cannot “hover” over elements. Therefore, interfaces should be designed to work entirely without hover states, with hover-specific enhancements added for devices that support them.

There are several ways to detect touch/hover capability via CSS and JavaScript. For consistency, we recommend using Discourse’s helpers instead of those CSS/JS APIs directly.

For CSS, you can target the .discourse-touch and .discourse-no-touch classes, which are added to the <html> element. These are determined based on the (any-pointer: coarse) media query.

For example:

html.discourse-touch {
  // SCSS rules here will apply to devices with a touch screen,
  // including mobiles/tablets and laptops/desktops with touch screens.
}

html.discourse-no-touch {
  // SCSS rules here will apply to devices with no touch screen.
}

This information is also available in Ember components via the capabilities service:

import Component from "@glimmer/component";
import { service } from "@ember/service";

class MyComponent extends Component {
  @service capabilities;

  <template>
    {{#if this.capabilities.touch}}
      This text will be displayed for devices with a touch screen
    {{/if}}

    {{#unless this.capabilities.touch}}
      This text will be displayed for devices with no touch screen
    {{/unless}}
  </template>
}

Legacy Mobile / Desktop Modes

Historically, Discourse shipped two completely different layouts and stylesheets for “mobile” and “desktop” views, based on the browser’s user-agent. Developers would target these modes by putting CSS in specific mobile/desktop directories, by using the .mobile-view/.desktop-view HTML classes, and the site.mobileView boolean in JavaScript.

These techniques are now considered deprecated and should be replaced with the viewport and capability-based strategies discussed in the next document. For backwards-compatibility, legacy desktop/mobile CSS is used when the viewport is larger/smaller than the sm threshold.

See also


This document is version controlled - suggest changes on github.

13 个赞

那么类似这样的东西将被弃用?

@service site;
...
const mobileView = this.site.mobileView;

如果在静态上下文中执行此操作,那么是的,这与即将推出的“基于视口的移动模式”(目前已禁用)不兼容。

如果像这样在自动跟踪上下文中执行检查:

@service site;
...

<template>
  {{#if this.site.mobileView}}
    ...
  {{/if}}
</template>

那么 Ember 将在 mobileView 布尔值更改时(即浏览器大小调整时)自动重新渲染内容。所以没关系。

所以可以确定的是,将其放入 getter 中已弃用,但将其放入 <template> 中则没有?

将其放入 getter 中也是可以的,因为 Ember 会自动跟踪它。

@service site;

get shouldRender() {
  return this.site.mobileView;
}

<template>
  {{#if this.shouldRender}}
    ...
  {{/if}}
</template>

^^ 这样就可以了

一个不好的例子是

export default apiInitializer((api) => {
  if (api.container.lookup("service:site").mobileView) {
    api.renderInOutlet("some-outlet", <template>My content</template>)
  }
});

因为在这种情况下,mobileView 只在应用程序启动时进行检查。调整浏览器大小不会重新运行初始化程序。

所以你会重构为类似这样的东西

export default apiInitializer((api) => {
  const site = api.container.lookup("service:site");
  api.renderInOutlet("some-outlet", <template>
    {{#if site.mobileView}}My content{{/if}}
  </template>);
});

这样,当调整浏览器大小时,对 mobileView 的更改就会生效。

3 个赞

明白了。谢谢你的解释!

1 个赞

(作者已删除帖子)

1 个赞

普遍的建议是:不要这样做。为什么这类体验会因屏幕尺寸而异?

一个有用的思想实验是:您期望它在折叠手机或平板电脑上如何表现,这些设备并不明确属于移动/桌面类别。

如果您确实希望这种行为更改基于浏览器的用户代理(就像旧的移动/桌面模式一样),那么我们有 capabilities.isMobileDevice,它会检查用户代理字符串中是否包含“mobile”一词:

1 个赞

嗯,在我的例子中,我为桌面端提供了将主页切换到标签交叉路由的选项——它的界面在移动设备上不存在……(尽管路由实际上有效——附加控件已隐藏)

……但你说得对,我可能会重新考虑!

1 个赞

有意思!我想知道这是故意的吗……我觉得它应该能在任何设备上运行 :thinking:

2 个赞

所以,这意味着 Discourse 将要弃用 pull-left 吗?因为那个类实在太难用了,我希望能看到它消失。

那样会很棒的 :wink:

解决方案在消息中

不要有条件地包含组件,而是始终包含它,并让组件有条件地渲染自身。

1 个赞

我理解你的意思,但我并不拥有这个组件,它是核心(core)的一部分,并且位于特定的路由上——如果核心(core)能让它在移动设备和桌面设备上都能工作,那将是最好的解决方案。

目前你可以将此页面设为(全局)主页,但在移动设备上这样做毫无意义,因为它无法在移动设备上运行。

我将给你另一个目前尚未完全利用且有点棘手的例子——“分类”页面——在桌面上保持原样,但在移动设备上可以将其变成一个“最新”页面,方法是隐藏“分类”面板,只保留“主题列表”——因为在我看来,(在移动设备上)只有“分类”视图而没有“主题列表”很糟糕。

但那样的话,在移动设备上它就不再是一个“分类”页面了。

现在,由于移动主页主题组件不再工作(因为你无法在初始化期间识别设备),这种情况变得更加严重。

因此,我认为发现路由(discovery routes)可能需要某种重新思考,以实现互操作性和适应主流设备的需求。

2 个赞