2017-09-02 06:59:50 +08:00
|
|
|
// Common
|
|
|
|
// global styles that apply to the Discourse application specifically
|
|
|
|
// BEWARE: changing these styles implies they take effect anywhere they are seen
|
|
|
|
// throughout the Discourse application
|
|
|
|
|
2023-11-29 03:10:41 +08:00
|
|
|
:root {
|
|
|
|
--d-input-bg-color: var(--secondary);
|
|
|
|
--d-input-text-color: var(--primary);
|
|
|
|
--d-input-border: 1px solid var(--primary-400);
|
DEV: form-kit
This PR introduces FormKit, a component-based form library designed to simplify form creation and management. This library provides a single `Form` component, various field components, controls, validation mechanisms, and customization options. Additionally, it includes helpers to facilitate testing and writing specifications for forms.
1. **Form Component**:
- The main component that encapsulates form logic and structure.
- Yields various utilities like `Field`, `Submit`, `Alert`, etc.
**Example Usage**:
```gjs
import Form from "discourse/form";
<template>
<Form as |form|>
<form.Field
@name="username"
@title="Username"
@validation="required"
as |field|
>
<field.Input />
</form.Field>
<form.Field @name="age" @title="Age" as |field|>
<field.Input @type="number" />
</form.Field>
<form.Submit />
</Form>
</template>
```
2. **Validation**:
- Built-in validation rules such as `required`, `number`, `length`, and `url`.
- Custom validation callbacks for more complex validation logic.
**Example Usage**:
```javascript
validateUsername(name, value, data, { addError }) {
if (data.bar / 2 === value) {
addError(name, "That's not how maths work.");
}
}
```
```hbs
<form.Field @name="username" @validate={{this.validateUsername}} />
```
3. **Customization**:
- Plugin outlets for extending form functionality.
- Styling capabilities through propagated attributes.
- Custom controls with properties provided by `form` and `field`.
**Example Usage**:
```hbs
<Form class="my-form" as |form|>
<form.Field class="my-field" as |field|>
<MyCustomControl id={{field.id}} @onChange={{field.set}} />
</form.Field>
</Form>
```
4. **Helpers for Testing**:
- Test assertions for form and field validation.
**Example usage**:
```javascript
assert.form().hasErrors("the form shows errors");
assert.form().field("foo").hasValue("bar", "user has set the value");
```
- Helper for interacting with he form
**Example usage**:
```javascript
await formKit().field("foo").fillIn("bar");
```
5. **Page Object for System Specs**:
- Page objects for interacting with forms in system specs.
- Methods for submitting forms, checking alerts, and interacting with fields.
**Example Usage**:
```ruby
form = PageObjects::Components::FormKit.new(".my-form")
form.submit
expect(form).to have_an_alert("message")
```
**Field Interactions**:
```ruby
field = form.field("foo")
expect(field).to have_value("bar")
field.fill_in("bar")
```
6. **Collections handling**:
- A specific component to handle array of objects
**Example Usage**:
```gjs
<Form @data={{hash foo=(array (hash bar=1) (hash bar=2))}} as |form|>
<form.Collection @name="foo" as |collection|>
<collection.Field @name="bar" @title="Bar" as |field|>
<field.Input />
</collection.Field>
</form.Collection>
</Form>
```
2024-07-17 17:59:35 +08:00
|
|
|
--d-input-bg-color--disabled: var(--primary-very-low);
|
|
|
|
--d-input-text-color--disabled: var(--primary-medium);
|
2023-11-29 03:10:41 +08:00
|
|
|
--d-input-border--disabled: 1px solid var(--primary-low);
|
2024-06-24 21:54:34 +08:00
|
|
|
--d-nav-color: var(--primary);
|
|
|
|
--d-nav-bg-color: transparent;
|
|
|
|
--d-nav-color--hover: var(--primary);
|
|
|
|
--d-nav-bg-color--hover: var(--d-hover);
|
|
|
|
--d-nav-color--active: var(--tertiary);
|
|
|
|
--d-nav-bg-color--active: transparent;
|
|
|
|
--d-nav-border-color--active: var(--d-nav-color--active);
|
|
|
|
--d-nav-underline-height: 0.125em;
|
2024-03-28 00:26:24 +08:00
|
|
|
--safe-area-inset-bottom: env(safe-area-inset-bottom);
|
2023-11-29 03:10:41 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
// Animation Keyframes
|
|
|
|
@keyframes rotate-forever {
|
|
|
|
0% {
|
|
|
|
transform: rotate(0deg);
|
|
|
|
}
|
|
|
|
100% {
|
|
|
|
transform: rotate(360deg);
|
|
|
|
}
|
2015-07-20 15:47:53 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
@keyframes background-fade-highlight {
|
|
|
|
0% {
|
2020-08-04 10:57:10 +08:00
|
|
|
background-color: var(--tertiary-low);
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
100% {
|
|
|
|
background-color: transparent;
|
2014-10-29 07:46:05 +08:00
|
|
|
}
|
2014-05-20 11:55:46 +08:00
|
|
|
}
|
|
|
|
|
2019-04-27 00:29:48 +08:00
|
|
|
// placeholder
|
|
|
|
@keyframes placeHolderShimmer {
|
|
|
|
0% {
|
|
|
|
background-position: -1000px 0;
|
|
|
|
}
|
|
|
|
100% {
|
|
|
|
background-position: 1100px 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-15 05:31:43 +08:00
|
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
|
|
.placeholder-animation {
|
|
|
|
animation-duration: 4s;
|
|
|
|
animation-fill-mode: forwards;
|
|
|
|
animation-iteration-count: infinite;
|
|
|
|
animation-name: placeHolderShimmer;
|
|
|
|
animation-timing-function: linear;
|
|
|
|
background: var(--primary-very-low);
|
|
|
|
background: linear-gradient(
|
|
|
|
to right,
|
|
|
|
var(--primary-very-low) 10%,
|
|
|
|
var(--primary-low) 18%,
|
|
|
|
var(--primary-very-low) 33%
|
|
|
|
);
|
|
|
|
}
|
2019-04-27 00:29:48 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
// Base Elements
|
|
|
|
html {
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
body {
|
|
|
|
background-attachment: fixed;
|
|
|
|
background-size: cover;
|
|
|
|
min-height: 100%;
|
2023-02-16 23:49:17 +08:00
|
|
|
box-sizing: border-box;
|
2017-09-02 06:59:50 +08:00
|
|
|
|
|
|
|
@include clearfix;
|
2014-05-20 11:55:46 +08:00
|
|
|
}
|
|
|
|
|
2018-01-19 15:12:30 +08:00
|
|
|
// setting a static limit on big and small prevents nesting abuse
|
2014-05-26 23:33:47 +08:00
|
|
|
big {
|
2022-10-12 21:31:59 +08:00
|
|
|
font-size: var(--font-up-5);
|
2014-05-26 23:33:47 +08:00
|
|
|
}
|
2014-11-03 08:23:00 +08:00
|
|
|
small {
|
2022-10-12 21:31:59 +08:00
|
|
|
font-size: var(--font-down-2);
|
2014-11-03 08:23:00 +08:00
|
|
|
}
|
|
|
|
|
2014-05-20 11:55:46 +08:00
|
|
|
blockquote {
|
2015-08-20 01:27:17 +08:00
|
|
|
@include post-aside;
|
2015-05-19 17:40:19 +08:00
|
|
|
clear: both;
|
2014-05-20 11:55:46 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
h1,
|
|
|
|
h2,
|
|
|
|
h3,
|
|
|
|
h4,
|
|
|
|
h5,
|
|
|
|
h6 {
|
2022-10-12 22:05:42 +08:00
|
|
|
font-family: var(--heading-font-family);
|
2017-09-02 06:59:50 +08:00
|
|
|
margin-top: 0;
|
2018-06-08 17:49:31 +08:00
|
|
|
margin-bottom: 0.5rem;
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
|
2019-10-03 02:47:29 +08:00
|
|
|
a.cancel {
|
|
|
|
margin-left: 1.25em;
|
|
|
|
line-height: normal;
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary-high);
|
2024-06-21 01:51:20 +08:00
|
|
|
transition: var(--d-button-transition);
|
2019-10-03 02:47:29 +08:00
|
|
|
&:hover {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--danger);
|
2019-10-03 02:47:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
ul.breadcrumb {
|
|
|
|
margin: 0 10px 0 10px;
|
|
|
|
}
|
|
|
|
|
2014-05-26 14:17:25 +08:00
|
|
|
a.no-href {
|
2014-04-21 03:17:11 +08:00
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
img.avatar {
|
|
|
|
border-radius: 50%;
|
2014-07-02 03:24:04 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
// don't wrap relative dates; we want Jul 26, '15, not: Jul
|
|
|
|
// 26,
|
|
|
|
// '15
|
|
|
|
span.relative-date {
|
2018-06-08 17:49:31 +08:00
|
|
|
white-space: nowrap;
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
2014-07-02 01:39:54 +08:00
|
|
|
|
2024-02-16 00:27:51 +08:00
|
|
|
legend {
|
|
|
|
color: var(--primary-high);
|
|
|
|
font-weight: bold;
|
DEV: form-kit
This PR introduces FormKit, a component-based form library designed to simplify form creation and management. This library provides a single `Form` component, various field components, controls, validation mechanisms, and customization options. Additionally, it includes helpers to facilitate testing and writing specifications for forms.
1. **Form Component**:
- The main component that encapsulates form logic and structure.
- Yields various utilities like `Field`, `Submit`, `Alert`, etc.
**Example Usage**:
```gjs
import Form from "discourse/form";
<template>
<Form as |form|>
<form.Field
@name="username"
@title="Username"
@validation="required"
as |field|
>
<field.Input />
</form.Field>
<form.Field @name="age" @title="Age" as |field|>
<field.Input @type="number" />
</form.Field>
<form.Submit />
</Form>
</template>
```
2. **Validation**:
- Built-in validation rules such as `required`, `number`, `length`, and `url`.
- Custom validation callbacks for more complex validation logic.
**Example Usage**:
```javascript
validateUsername(name, value, data, { addError }) {
if (data.bar / 2 === value) {
addError(name, "That's not how maths work.");
}
}
```
```hbs
<form.Field @name="username" @validate={{this.validateUsername}} />
```
3. **Customization**:
- Plugin outlets for extending form functionality.
- Styling capabilities through propagated attributes.
- Custom controls with properties provided by `form` and `field`.
**Example Usage**:
```hbs
<Form class="my-form" as |form|>
<form.Field class="my-field" as |field|>
<MyCustomControl id={{field.id}} @onChange={{field.set}} />
</form.Field>
</Form>
```
4. **Helpers for Testing**:
- Test assertions for form and field validation.
**Example usage**:
```javascript
assert.form().hasErrors("the form shows errors");
assert.form().field("foo").hasValue("bar", "user has set the value");
```
- Helper for interacting with he form
**Example usage**:
```javascript
await formKit().field("foo").fillIn("bar");
```
5. **Page Object for System Specs**:
- Page objects for interacting with forms in system specs.
- Methods for submitting forms, checking alerts, and interacting with fields.
**Example Usage**:
```ruby
form = PageObjects::Components::FormKit.new(".my-form")
form.submit
expect(form).to have_an_alert("message")
```
**Field Interactions**:
```ruby
field = form.field("foo")
expect(field).to have_value("bar")
field.fill_in("bar")
```
6. **Collections handling**:
- A specific component to handle array of objects
**Example Usage**:
```gjs
<Form @data={{hash foo=(array (hash bar=1) (hash bar=2))}} as |form|>
<form.Collection @name="foo" as |collection|>
<collection.Field @name="bar" @title="Bar" as |field|>
<field.Input />
</collection.Field>
</form.Collection>
</Form>
```
2024-07-17 17:59:35 +08:00
|
|
|
font-size: var(--font-down-1-rem);
|
2024-02-16 00:27:51 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
label {
|
2018-09-19 20:37:04 +08:00
|
|
|
display: flex;
|
2017-09-02 06:59:50 +08:00
|
|
|
margin-bottom: 5px;
|
2018-09-19 23:48:48 +08:00
|
|
|
align-items: flex-start;
|
2023-10-23 23:36:36 +08:00
|
|
|
color: var(--primary-high);
|
|
|
|
|
|
|
|
&:not(.checkbox-label) {
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
2019-03-29 03:10:31 +08:00
|
|
|
> .d-icon {
|
|
|
|
align-self: center;
|
|
|
|
margin-right: 4px;
|
|
|
|
}
|
2021-01-12 02:35:41 +08:00
|
|
|
a {
|
|
|
|
// flex removes whitespace characters between text nodes and elements
|
|
|
|
// so we need to add it back
|
|
|
|
margin: 0 0.25em;
|
|
|
|
}
|
2017-08-19 00:36:21 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
input {
|
|
|
|
&[type="radio"],
|
|
|
|
&[type="checkbox"] {
|
2018-10-03 00:04:37 +08:00
|
|
|
margin-top: 0.17em;
|
|
|
|
margin-right: 0.43em;
|
2018-10-04 10:26:05 +08:00
|
|
|
margin-left: 0.1em;
|
2022-10-12 22:05:42 +08:00
|
|
|
line-height: var(--line-height-small);
|
2017-09-02 06:59:50 +08:00
|
|
|
cursor: pointer;
|
2018-10-04 10:26:05 +08:00
|
|
|
flex-shrink: 0; // Adding for safety, Safari will shrink checkboxes
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
&[type="submit"],
|
|
|
|
&[type="reset"],
|
|
|
|
&[type="button"],
|
|
|
|
&[type="radio"],
|
|
|
|
&[type="checkbox"] {
|
|
|
|
width: auto;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.invalid {
|
2020-08-04 10:57:10 +08:00
|
|
|
background-color: var(--danger-low);
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.radio &[type="radio"],
|
|
|
|
.checkbox &[type="checkbox"] {
|
|
|
|
float: left;
|
|
|
|
margin-left: -18px;
|
|
|
|
}
|
2017-11-10 04:03:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
input {
|
|
|
|
&[type="text"],
|
|
|
|
&[type="password"],
|
|
|
|
&[type="datetime"],
|
|
|
|
&[type="datetime-local"],
|
|
|
|
&[type="date"],
|
|
|
|
&[type="month"],
|
|
|
|
&[type="time"],
|
|
|
|
&[type="week"],
|
|
|
|
&[type="number"],
|
|
|
|
&[type="email"],
|
|
|
|
&[type="url"],
|
|
|
|
&[type="search"],
|
|
|
|
&[type="tel"],
|
2024-01-31 03:25:48 +08:00
|
|
|
&[type="color"] {
|
2017-11-28 04:23:18 +08:00
|
|
|
@include appearance-none;
|
2021-09-09 23:01:56 +08:00
|
|
|
@include form-item-sizing;
|
2017-11-10 04:03:19 +08:00
|
|
|
display: inline-block;
|
|
|
|
margin-bottom: 9px;
|
2023-11-29 03:10:41 +08:00
|
|
|
color: var(--d-input-text-color);
|
|
|
|
background-color: var(--d-input-bg-color);
|
|
|
|
border: var(--d-input-border);
|
2022-11-17 00:35:09 +08:00
|
|
|
border-radius: var(--d-input-border-radius);
|
2024-07-05 02:56:58 +08:00
|
|
|
color-scheme: var(--scheme-type);
|
2017-11-10 04:03:19 +08:00
|
|
|
&:focus {
|
2021-02-04 00:45:54 +08:00
|
|
|
@include default-focus;
|
2017-11-10 04:03:19 +08:00
|
|
|
}
|
|
|
|
}
|
2021-09-09 23:01:56 +08:00
|
|
|
|
|
|
|
&[type="time"] {
|
|
|
|
max-width: 140px;
|
|
|
|
}
|
2017-11-10 04:03:19 +08:00
|
|
|
}
|
|
|
|
|
2022-01-31 12:35:51 +08:00
|
|
|
input[type="search"] {
|
|
|
|
&::-webkit-search-cancel-button,
|
|
|
|
&::-webkit-search-decoration {
|
|
|
|
-webkit-appearance: none;
|
|
|
|
appearance: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-09 23:01:56 +08:00
|
|
|
// Fixes Safari height inconsistency
|
|
|
|
::-webkit-datetime-edit {
|
|
|
|
display: inline;
|
2020-12-16 13:40:30 +08:00
|
|
|
}
|
|
|
|
|
2021-09-09 23:01:56 +08:00
|
|
|
// Fixes Webkit inconsistencies (Safari/Chrome)
|
|
|
|
::-webkit-datetime-edit-fields-wrapper,
|
|
|
|
::-webkit-datetime-edit-text,
|
|
|
|
::-webkit-datetime-edit-month-field,
|
|
|
|
::-webkit-datetime-edit-day-field,
|
|
|
|
::-webkit-datetime-edit-year-field {
|
|
|
|
padding-top: 0;
|
|
|
|
padding-bottom: 0;
|
|
|
|
}
|
2018-10-05 03:47:14 +08:00
|
|
|
|
2021-09-09 23:01:56 +08:00
|
|
|
::placeholder {
|
|
|
|
text-overflow: ellipsis;
|
2018-10-05 03:47:14 +08:00
|
|
|
}
|
|
|
|
|
2017-11-10 04:03:19 +08:00
|
|
|
textarea {
|
2021-09-09 23:01:56 +08:00
|
|
|
padding: $vpad $hpad;
|
|
|
|
box-sizing: border-box;
|
2017-11-10 04:03:19 +08:00
|
|
|
height: auto;
|
2020-08-04 10:57:10 +08:00
|
|
|
background-color: var(--secondary);
|
2023-10-23 23:36:36 +08:00
|
|
|
border: 1px solid var(--primary-400);
|
2022-01-17 15:58:57 +08:00
|
|
|
border-radius: 0;
|
|
|
|
|
2017-11-10 04:03:19 +08:00
|
|
|
&:focus {
|
2021-02-04 00:45:54 +08:00
|
|
|
@include default-focus;
|
2017-11-10 04:03:19 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
2020-08-04 10:57:10 +08:00
|
|
|
border: 1px solid var(--primary-low);
|
2017-08-19 00:36:21 +08:00
|
|
|
}
|
2015-03-28 02:42:27 +08:00
|
|
|
|
2019-02-27 10:40:17 +08:00
|
|
|
table {
|
|
|
|
th {
|
|
|
|
font-weight: normal;
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary-medium);
|
2019-02-27 10:40:17 +08:00
|
|
|
text-align: left;
|
|
|
|
padding: 0.5em;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-29 03:10:41 +08:00
|
|
|
input,
|
|
|
|
select,
|
|
|
|
textarea {
|
2023-11-29 05:21:36 +08:00
|
|
|
color: var(--d-input-text-color);
|
2023-11-29 03:10:41 +08:00
|
|
|
caret-color: currentColor;
|
|
|
|
|
|
|
|
&[disabled],
|
|
|
|
&[readonly] {
|
|
|
|
cursor: not-allowed;
|
2023-11-29 05:21:36 +08:00
|
|
|
color: var(--d-input-text-color--disabled);
|
2023-11-29 03:10:41 +08:00
|
|
|
background-color: var(--d-input-bg-color--disabled);
|
|
|
|
border: var(--d-input-border--disabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
&:focus:required:invalid {
|
|
|
|
color: var(--danger);
|
|
|
|
border-color: var(--danger);
|
|
|
|
outline: 1px solid var(--danger);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
// Common Classes
|
2019-02-27 10:40:17 +08:00
|
|
|
|
|
|
|
.sortable {
|
|
|
|
white-space: nowrap;
|
|
|
|
.discourse-no-touch & {
|
2021-04-02 02:19:59 +08:00
|
|
|
&:hover,
|
|
|
|
&:focus {
|
2020-08-04 10:57:10 +08:00
|
|
|
background-color: var(--primary-low);
|
2019-02-27 10:40:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
.d-icon {
|
|
|
|
margin-left: 0.25em;
|
|
|
|
}
|
|
|
|
@include unselectable;
|
2022-10-21 00:28:03 +08:00
|
|
|
cursor: pointer;
|
2024-11-20 04:38:03 +08:00
|
|
|
|
|
|
|
button {
|
|
|
|
background: none;
|
|
|
|
border: none;
|
|
|
|
}
|
2019-02-27 10:40:17 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
.radio,
|
|
|
|
.checkbox {
|
|
|
|
min-height: 18px;
|
|
|
|
padding-left: 18px;
|
|
|
|
|
|
|
|
.controls > &:first-child {
|
|
|
|
padding-top: 5px;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.inline {
|
|
|
|
display: inline-block;
|
|
|
|
padding-top: 5px;
|
|
|
|
margin-bottom: 0;
|
|
|
|
vertical-align: middle;
|
2014-04-21 03:17:11 +08:00
|
|
|
}
|
2017-08-19 00:36:21 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
.radio.inline .radio.inline,
|
|
|
|
.checkbox.inline .checkbox.inline {
|
2024-05-22 01:13:38 +08:00
|
|
|
margin-left: 0.67em;
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.container {
|
|
|
|
@extend .clearfix;
|
|
|
|
}
|
|
|
|
|
|
|
|
.wrap {
|
2024-05-22 01:13:38 +08:00
|
|
|
--d-wrap-padding-h: 0.67em;
|
2022-06-29 10:49:01 +08:00
|
|
|
max-width: var(--d-max-width);
|
2017-09-02 06:59:50 +08:00
|
|
|
margin-right: auto;
|
|
|
|
margin-left: auto;
|
2024-02-07 00:50:49 +08:00
|
|
|
padding: 0 var(--d-wrap-padding-h);
|
2017-09-02 06:59:50 +08:00
|
|
|
.contents {
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.boxed {
|
|
|
|
&.white {
|
2020-08-04 10:57:10 +08:00
|
|
|
background-color: var(--secondary);
|
2014-04-21 03:17:11 +08:00
|
|
|
}
|
2017-08-19 00:36:21 +08:00
|
|
|
}
|
2014-04-24 08:48:04 +08:00
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
.full-width {
|
|
|
|
margin-left: 12px;
|
|
|
|
}
|
|
|
|
|
2017-08-19 00:36:21 +08:00
|
|
|
.clear-transitions {
|
2018-06-08 17:49:31 +08:00
|
|
|
transition: none !important;
|
2017-08-19 00:36:21 +08:00
|
|
|
}
|
2014-05-03 05:46:03 +08:00
|
|
|
|
2017-08-19 00:36:21 +08:00
|
|
|
.tip {
|
|
|
|
display: inline-block;
|
|
|
|
&.good {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--success);
|
2015-09-16 23:54:09 +08:00
|
|
|
}
|
2017-08-19 00:36:21 +08:00
|
|
|
&.bad {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--danger);
|
2015-09-17 04:04:48 +08:00
|
|
|
}
|
2017-08-19 00:36:21 +08:00
|
|
|
}
|
2014-04-21 03:17:11 +08:00
|
|
|
|
2017-08-19 00:36:21 +08:00
|
|
|
.avatar-wrapper {
|
2020-08-04 10:57:10 +08:00
|
|
|
background-color: var(--secondary);
|
2017-08-19 00:36:21 +08:00
|
|
|
display: inline-block;
|
|
|
|
border-radius: 50%;
|
|
|
|
}
|
2017-05-19 05:08:45 +08:00
|
|
|
|
2020-04-01 07:09:20 +08:00
|
|
|
.unread-high-priority-notifications {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--secondary);
|
|
|
|
background: var(--success);
|
2017-09-02 06:59:50 +08:00
|
|
|
|
|
|
|
&.badge-notification[href] {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--secondary);
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
2014-07-26 01:33:38 +08:00
|
|
|
}
|
2014-08-22 22:45:51 +08:00
|
|
|
|
2020-12-18 23:03:51 +08:00
|
|
|
.d-header .header-dropdown-toggle .do-not-disturb-background {
|
|
|
|
position: absolute;
|
2022-05-27 17:15:14 +08:00
|
|
|
left: 0;
|
2020-12-18 23:03:51 +08:00
|
|
|
bottom: -1px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.do-not-disturb-background {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
2024-11-19 09:25:41 +08:00
|
|
|
width: 1em;
|
2024-02-01 06:56:07 +08:00
|
|
|
background-color: var(--secondary);
|
2020-12-18 23:03:51 +08:00
|
|
|
border-radius: 50%;
|
2024-11-19 09:25:41 +08:00
|
|
|
height: 1em;
|
|
|
|
box-shadow: 0px 0px 0px 2px var(--secondary);
|
2020-12-18 23:03:51 +08:00
|
|
|
|
2024-02-01 06:56:07 +08:00
|
|
|
.d-icon.d-icon-discourse-dnd {
|
|
|
|
color: var(--header_primary-medium) !important;
|
|
|
|
font-size: 1em;
|
|
|
|
height: 1em;
|
|
|
|
width: 1em;
|
2020-12-18 23:03:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-27 17:15:14 +08:00
|
|
|
.d-header .header-dropdown-toggle .user-status-background {
|
|
|
|
position: absolute;
|
|
|
|
right: -3px;
|
|
|
|
bottom: -1px;
|
|
|
|
z-index: 1002;
|
|
|
|
}
|
|
|
|
|
|
|
|
.user-status-background {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
width: 1.25em;
|
|
|
|
height: 1.25em;
|
2022-06-22 23:40:21 +08:00
|
|
|
background-color: var(--secondary);
|
2022-05-27 17:15:14 +08:00
|
|
|
border-radius: 50%;
|
|
|
|
|
|
|
|
.emoji {
|
|
|
|
width: 14px;
|
|
|
|
height: 14px;
|
|
|
|
display: block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-05 23:12:22 +08:00
|
|
|
.user-menu .quick-access-panel li.user-status .relative-date {
|
|
|
|
text-align: left;
|
|
|
|
font-size: var(--font-down-3);
|
|
|
|
padding-top: 0.45em;
|
|
|
|
margin-left: 0.75em;
|
|
|
|
color: var(--primary-medium);
|
|
|
|
}
|
|
|
|
|
2020-12-31 22:39:06 +08:00
|
|
|
.user-menu .quick-access-panel li.do-not-disturb {
|
2020-12-18 23:03:51 +08:00
|
|
|
display: flex;
|
|
|
|
flex: 0 0 100%;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
align-items: center;
|
2020-12-31 22:39:06 +08:00
|
|
|
background: var(--secondary);
|
2020-12-18 23:03:51 +08:00
|
|
|
|
|
|
|
.do-not-disturb-inner-container {
|
|
|
|
display: flex;
|
2020-12-31 22:39:06 +08:00
|
|
|
width: 100%;
|
2020-12-18 23:03:51 +08:00
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
.do-not-disturb-label {
|
|
|
|
display: flex;
|
2020-12-31 22:39:06 +08:00
|
|
|
align-items: center;
|
2020-12-18 23:03:51 +08:00
|
|
|
}
|
|
|
|
|
2020-12-31 22:39:06 +08:00
|
|
|
.relative-date {
|
2020-12-18 23:03:51 +08:00
|
|
|
text-align: left;
|
2022-10-12 21:31:59 +08:00
|
|
|
font-size: var(--font-down-3);
|
2020-12-31 22:39:06 +08:00
|
|
|
padding-top: 3px;
|
|
|
|
margin-left: 0.75em;
|
2020-12-18 23:03:51 +08:00
|
|
|
color: var(--primary-medium);
|
|
|
|
}
|
|
|
|
|
2020-12-31 22:39:06 +08:00
|
|
|
.d-icon-toggle-off,
|
|
|
|
.d-icon-toggle-on {
|
|
|
|
padding-top: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.d-icon-toggle-on {
|
|
|
|
color: var(--tertiary);
|
2020-12-18 23:03:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.do-not-disturb-modal {
|
|
|
|
.do-not-disturb-choice {
|
|
|
|
display: grid;
|
|
|
|
grid-template-columns: 2em 1fr auto;
|
|
|
|
grid-template-rows: auto auto;
|
|
|
|
align-items: center;
|
|
|
|
cursor: pointer;
|
|
|
|
padding: 0.5em 0;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
background-color: var(--tertiary-low);
|
|
|
|
}
|
|
|
|
|
|
|
|
label {
|
|
|
|
margin-bottom: 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-22 22:45:51 +08:00
|
|
|
.fade {
|
|
|
|
opacity: 0;
|
|
|
|
transition: opacity 0.15s linear;
|
2014-11-06 09:13:51 +08:00
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
&.in {
|
|
|
|
opacity: 1;
|
2014-11-06 09:13:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-14 03:15:36 +08:00
|
|
|
.inline-spinner {
|
|
|
|
display: inline-block;
|
|
|
|
margin: 0;
|
|
|
|
}
|
|
|
|
|
2014-11-11 22:22:14 +08:00
|
|
|
.spinner {
|
2014-12-05 06:05:47 +08:00
|
|
|
margin: 20px auto 20px auto;
|
2014-11-11 22:22:14 +08:00
|
|
|
position: relative;
|
|
|
|
-webkit-animation: rotate-forever 1s infinite linear;
|
|
|
|
animation: rotate-forever 1s infinite linear;
|
|
|
|
height: 30px;
|
|
|
|
width: 30px;
|
2020-08-04 10:57:10 +08:00
|
|
|
border: 4px solid var(--primary-low-mid);
|
2014-11-11 22:22:14 +08:00
|
|
|
border-right-color: transparent;
|
|
|
|
border-radius: 50%;
|
2014-11-14 03:15:36 +08:00
|
|
|
|
|
|
|
&.small {
|
|
|
|
width: 10px;
|
|
|
|
height: 10px;
|
|
|
|
margin: 0;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
2014-11-06 09:13:51 +08:00
|
|
|
}
|
2016-02-07 06:22:46 +08:00
|
|
|
|
2016-06-07 02:18:15 +08:00
|
|
|
.content-list {
|
|
|
|
h3 {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary-medium);
|
2022-10-12 21:31:59 +08:00
|
|
|
font-size: var(--font-up-1);
|
2016-06-07 02:18:15 +08:00
|
|
|
padding-left: 5px;
|
|
|
|
margin-bottom: 10px;
|
|
|
|
}
|
|
|
|
|
|
|
|
ul {
|
|
|
|
list-style: none;
|
|
|
|
margin: 0;
|
|
|
|
|
|
|
|
li {
|
2020-08-04 10:57:10 +08:00
|
|
|
border-bottom: 1px solid var(--primary-low);
|
2016-06-07 02:18:15 +08:00
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
&:first-of-type {
|
2020-08-04 10:57:10 +08:00
|
|
|
border-top: 1px solid var(--primary-low);
|
2016-06-07 02:18:15 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
a {
|
|
|
|
display: block;
|
|
|
|
padding: 10px;
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary);
|
2017-09-02 06:59:50 +08:00
|
|
|
|
|
|
|
&:hover {
|
2020-08-04 10:57:10 +08:00
|
|
|
background-color: var(--primary-low);
|
|
|
|
color: var(--primary);
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
font-weight: bold;
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary);
|
2023-02-20 22:14:54 +08:00
|
|
|
background: var(--d-selected);
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
2016-06-07 02:18:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
.form-vertical {
|
|
|
|
input,
|
|
|
|
textarea,
|
2021-09-09 23:01:56 +08:00
|
|
|
select {
|
2017-09-02 06:59:50 +08:00
|
|
|
display: inline-block;
|
|
|
|
margin-bottom: 0;
|
2018-10-02 22:42:49 +08:00
|
|
|
flex: 0 0 auto;
|
2023-04-19 21:41:02 +08:00
|
|
|
max-width: 100%;
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
|
2022-12-14 00:13:48 +08:00
|
|
|
.control-label:not(.checkbox-label) {
|
2022-10-12 22:05:42 +08:00
|
|
|
font-family: var(--heading-font-family);
|
2017-09-02 06:59:50 +08:00
|
|
|
font-weight: bold;
|
2022-10-12 21:31:59 +08:00
|
|
|
font-size: var(--font-up-2);
|
2022-10-12 22:05:42 +08:00
|
|
|
line-height: var(--line-height-large);
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
|
2024-02-16 00:27:51 +08:00
|
|
|
.control-group,
|
2017-09-02 06:59:50 +08:00
|
|
|
.controls {
|
|
|
|
margin-left: 0;
|
2024-02-16 00:27:51 +08:00
|
|
|
label {
|
|
|
|
font-weight: normal;
|
|
|
|
}
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
2016-02-07 06:22:46 +08:00
|
|
|
}
|
2016-12-06 06:20:52 +08:00
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
// Special elements
|
2020-10-20 05:26:38 +08:00
|
|
|
|
2022-07-05 11:45:02 +08:00
|
|
|
#main-outlet-wrapper {
|
|
|
|
box-sizing: border-box;
|
|
|
|
width: 100%;
|
|
|
|
display: grid;
|
2024-03-08 05:19:47 +08:00
|
|
|
grid-template-areas:
|
|
|
|
"sidebar content"
|
|
|
|
"sidebar below-content";
|
|
|
|
grid-template-rows: 1fr auto;
|
2022-07-07 01:31:06 +08:00
|
|
|
grid-template-columns: 0 minmax(0, 1fr); // 0 column width needs to be set for CSS transitions
|
2022-07-05 11:45:02 +08:00
|
|
|
gap: 0;
|
|
|
|
|
|
|
|
#main-outlet {
|
|
|
|
grid-area: content;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-20 05:26:38 +08:00
|
|
|
#main-outlet {
|
2022-09-29 12:28:01 +08:00
|
|
|
padding-top: 1.5em;
|
2020-10-20 05:26:38 +08:00
|
|
|
}
|
|
|
|
|
2017-09-02 06:59:50 +08:00
|
|
|
#main {
|
|
|
|
img.avatar {
|
|
|
|
&.header {
|
|
|
|
width: 45px;
|
|
|
|
height: 45px;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.medium {
|
|
|
|
width: 32px;
|
|
|
|
height: 32px;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.small {
|
|
|
|
width: 25px;
|
|
|
|
height: 25px;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.tiny {
|
|
|
|
width: 20px;
|
|
|
|
height: 20px;
|
|
|
|
}
|
2016-12-06 06:20:52 +08:00
|
|
|
}
|
2017-09-02 06:59:50 +08:00
|
|
|
|
|
|
|
.user-list {
|
|
|
|
.user {
|
|
|
|
padding-bottom: 5px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#loading-message {
|
|
|
|
position: absolute;
|
2022-10-12 21:31:59 +08:00
|
|
|
font-size: var(--font-up-5);
|
2017-09-02 06:59:50 +08:00
|
|
|
text-align: center;
|
|
|
|
top: 120px;
|
|
|
|
left: 500px;
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary);
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#footer {
|
|
|
|
.container {
|
|
|
|
height: 50px;
|
|
|
|
.contents {
|
|
|
|
padding-top: 10px;
|
|
|
|
a[href] {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--secondary);
|
2017-09-02 06:59:50 +08:00
|
|
|
}
|
|
|
|
}
|
2016-12-06 06:20:52 +08:00
|
|
|
}
|
|
|
|
}
|
2018-03-26 17:33:03 +08:00
|
|
|
|
|
|
|
.inline {
|
|
|
|
display: inline;
|
|
|
|
}
|
2018-08-31 16:18:06 +08:00
|
|
|
|
2020-06-11 00:11:49 +08:00
|
|
|
.pref-email {
|
2024-05-22 23:47:50 +08:00
|
|
|
display: grid;
|
|
|
|
grid-template-areas:
|
|
|
|
"title title"
|
|
|
|
"email email"
|
|
|
|
"instructions controls";
|
|
|
|
grid-template-columns: 1fr auto;
|
|
|
|
align-items: center;
|
|
|
|
gap: 0 0.5em;
|
2020-06-11 00:11:49 +08:00
|
|
|
|
2024-05-22 23:47:50 +08:00
|
|
|
.control-label {
|
|
|
|
grid-area: title;
|
|
|
|
}
|
|
|
|
|
|
|
|
.emails {
|
|
|
|
grid-area: email;
|
|
|
|
}
|
|
|
|
|
|
|
|
.instructions {
|
|
|
|
grid-area: instructions;
|
|
|
|
}
|
|
|
|
|
|
|
|
.controls {
|
|
|
|
margin-top: 0.5em;
|
|
|
|
grid-area: controls;
|
|
|
|
}
|
|
|
|
|
|
|
|
.resend-email-confirmation {
|
|
|
|
background: transparent;
|
|
|
|
border: none;
|
|
|
|
color: var(--tertiary);
|
|
|
|
padding: 0;
|
|
|
|
text-align: left;
|
|
|
|
}
|
|
|
|
|
|
|
|
.row {
|
|
|
|
border-bottom: 1px solid var(--primary-low);
|
|
|
|
padding: 0.25em 0;
|
|
|
|
display: grid;
|
|
|
|
grid-template-areas:
|
|
|
|
"email dropdown"
|
|
|
|
"meta dropdown";
|
|
|
|
grid-template-columns: 1fr auto;
|
|
|
|
grid-template-rows: 1fr auto;
|
2020-06-11 00:11:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.email-first {
|
2024-05-22 23:47:50 +08:00
|
|
|
grid-area: email;
|
|
|
|
align-self: center;
|
|
|
|
overflow-wrap: break-word;
|
|
|
|
min-width: 0;
|
2020-06-11 00:11:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.email-second {
|
2024-05-22 23:47:50 +08:00
|
|
|
grid-area: meta;
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary-medium);
|
2020-06-11 00:11:49 +08:00
|
|
|
|
|
|
|
.primary {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--success);
|
2020-06-11 00:11:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.unconfirmed {
|
|
|
|
font-style: italic;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.email-dropdown {
|
2024-05-22 23:47:50 +08:00
|
|
|
grid-area: dropdown;
|
|
|
|
align-self: center;
|
|
|
|
justify-self: end;
|
|
|
|
summary {
|
2020-06-11 00:11:49 +08:00
|
|
|
background: transparent;
|
|
|
|
.d-icon {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary-high);
|
2020-06-11 00:11:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.dropdown-menu {
|
|
|
|
width: 120px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-07 08:22:04 +08:00
|
|
|
.topic-statuses {
|
2021-09-03 03:35:35 +08:00
|
|
|
// avoid adding margin/padding on this parent; sometimes it appears as an empty container
|
2018-12-07 08:22:04 +08:00
|
|
|
float: left;
|
|
|
|
.topic-status {
|
|
|
|
margin: 0;
|
2018-12-11 05:06:26 +08:00
|
|
|
display: inline-flex;
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--primary-medium);
|
2021-09-03 03:35:35 +08:00
|
|
|
margin-right: 0.2em;
|
2018-12-07 08:22:04 +08:00
|
|
|
.d-icon {
|
2020-11-23 09:16:41 +08:00
|
|
|
height: 0.74em;
|
2018-12-07 08:22:04 +08:00
|
|
|
width: 0.75em;
|
2018-12-11 05:06:26 +08:00
|
|
|
}
|
2018-12-07 08:22:04 +08:00
|
|
|
}
|
|
|
|
|
2020-02-27 21:25:32 +08:00
|
|
|
.topic-status-warning .d-icon-envelope {
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--danger);
|
2018-12-07 08:22:04 +08:00
|
|
|
}
|
|
|
|
}
|
2019-05-24 22:25:55 +08:00
|
|
|
|
2023-09-12 21:07:03 +08:00
|
|
|
.broken-theme-alert-banner {
|
2022-10-12 22:05:42 +08:00
|
|
|
font-size: var(--base-font-size);
|
2019-05-24 22:25:55 +08:00
|
|
|
font-weight: bold;
|
|
|
|
padding: 5px 0;
|
2022-02-11 17:16:18 +08:00
|
|
|
background: var(--danger);
|
2019-05-24 22:25:55 +08:00
|
|
|
text-align: center;
|
|
|
|
z-index: z("max");
|
2020-08-04 10:57:10 +08:00
|
|
|
color: var(--secondary);
|
2022-02-11 17:16:18 +08:00
|
|
|
|
|
|
|
a {
|
|
|
|
color: var(--secondary);
|
|
|
|
text-decoration: underline;
|
|
|
|
}
|
|
|
|
|
|
|
|
.theme-error-suffix {
|
|
|
|
font-weight: normal;
|
|
|
|
}
|
2019-05-24 22:25:55 +08:00
|
|
|
}
|
2021-01-22 21:39:16 +08:00
|
|
|
|
|
|
|
.controls {
|
|
|
|
.grouped-control {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
.grouped-control-label {
|
|
|
|
padding: 0.25em 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.grouped-control-field {
|
|
|
|
flex: 1 0 auto;
|
|
|
|
display: flex;
|
|
|
|
padding-bottom: 0.25em;
|
|
|
|
|
|
|
|
label {
|
|
|
|
margin: 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-01 01:43:30 +08:00
|
|
|
|
2024-03-22 05:52:43 +08:00
|
|
|
a#user-nav-skip-link,
|
2021-09-01 01:43:30 +08:00
|
|
|
a#skip-link {
|
|
|
|
padding: 0.25em 0.5em;
|
2021-09-09 09:28:55 +08:00
|
|
|
position: fixed;
|
|
|
|
top: -50px;
|
2021-09-01 01:43:30 +08:00
|
|
|
left: 1em;
|
|
|
|
color: var(--secondary);
|
|
|
|
background: var(--tertiary);
|
|
|
|
transition: top 0.3s ease-out;
|
|
|
|
z-index: z("header") + 1;
|
|
|
|
&:focus {
|
|
|
|
top: 0px;
|
|
|
|
transition: top 0.15s ease-in;
|
|
|
|
}
|
|
|
|
}
|
UX: improve touch, swipe, panning performance on mobile menus (#23775)
PERF: improve touch, swipe, panning performance on mobile menus
---
* stop event propagation on swipe events: other touch events were stealing a huge amount of time here. Stop event
propagation when handling pan events.
* animate with [web animations api](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API)
* prefer translate3d to hint for gpu rendering.
* query document for elements only on start move event, not on subsequent move
events
* remove unused calculations for directioned velocity and distance: all swipe/pan elements function in x/y direction only.
* re-implement scroll locking behavior.
re-implemented scroll lock behavior
---
With stop event propagation, we need to re-implement scroll locking on menu swipes.
Previously, this was using onTouchMove which was costly.
We may now use styling with overflow-y:hidden to lock scroll behavior.
overflow:hidden on html/body elements is now supported by iOS as of 2022
https://bugs.webkit.org/show_bug.cgi?id=153852
https://bugs.webkit.org/show_bug.cgi?id=220908
UX: improve swipe
---
Some improvements to get gestures and swipes feeling a little more polished.
This focuses on end gesture, and how we transfer it to a css animation to
complete a menu open/close action.
Multitouch: events may pan, scroll, and zoom - especially on iOS safari.
Cancelling the swipe event allows for a more pleasant zooming experience.
* ease-out on menus opening, linear on close
* calculate animation duration for opening and closing,
attempt to better transfer user swipe velocity to css animation.
* more timely close/open and cleanup from calculated animation timing.
* add animation to closing menus on cloak tap
* correctly animate menus with ease-in and ease-out
* add swipe cancel event on multitouch event
DEV
---
* lean on promises
js animations api gives us promises to listen to. Update test waiters
to use waitForPromise from @ember/test-waiters instead of reigster/unregister.
* convert swipe mixin to its own class.
Convert swipe callbacks to custom events on the element.
Move shared functions for max animation time and close logic to
new shared class.
swipe-events lib uses custom events to trigger callbacks, rather than assuming
implemented hard coded function from the mixin's base class. Custom events are
triggered from the bound element as swipestart, swipeend, swipe
Add shared convenience functions for swipe events so they can be more easily
shared.
A client receives an initial swipe event and can check some state to see if it
wants to handle the swipe event and if it doesn't, calling
`event.preventDefault();` will prevent `swipe` and `swipeend` events from firing
until another distinct swipestart event is fired. Swipe events will auto-cancel on multitouch.
The scroll lock has also exposed as its own utility class.
2023-10-17 02:27:00 +08:00
|
|
|
|
|
|
|
.scroll-lock {
|
|
|
|
overflow: hidden !important;
|
|
|
|
margin-right: var(--scroll-gap, 0);
|
|
|
|
}
|
2024-08-08 22:59:28 +08:00
|
|
|
|
|
|
|
.hbr-ember-outlet {
|
|
|
|
display: contents;
|
|
|
|
}
|