discourse/plugins/chat/assets/stylesheets/common/chat-message.scss
Joffrey JAFFEUX 2a10ea0e3f
DEV: FloatKit (#23650)
This PR introduces three new concepts to Discourse codebase through an addon called "FloatKit":

- menu
- tooltip
- toast


## Tooltips
### Component

Simple cases can be express with an API similar to DButton:

```hbs
<DTooltip 
  @Label={{i18n "foo.bar"}}
  @ICON="check"
  @content="Something"
/>
```

More complex cases can use blocks:

```hbs
<DTooltip>
  <:trigger>
   {{d-icon "check"}}
   <span>{{i18n "foo.bar"}}</span>
  </:trigger>
  <:content>
   Something
  </:content>
</DTooltip>
```

### Service

You can manually show a tooltip using the `tooltip` service:

```javascript
const tooltipInstance = await this.tooltip.show(
  document.querySelector(".my-span"),
  options
)

// and later manual close or destroy it
tooltipInstance.close();
tooltipInstance.destroy();

// you can also just close any open tooltip through the service
this.tooltip.close();
```

The service also allows you to register event listeners on a trigger, it removes the need for you to manage open/close of a tooltip started through the service:

```javascript
const tooltipInstance = this.tooltip.register(
  document.querySelector(".my-span"),
  options
)

// when done you can destroy the instance to remove the listeners
tooltipInstance.destroy();
```

Note that the service also allows you to use a custom component as content which will receive `@data` and `@close` as args:

```javascript
const tooltipInstance = await this.tooltip.show(
  document.querySelector(".my-span"),
  { 
    component: MyComponent,
    data: { foo: 1 }
  }
)
```

## Menus

Menus are very similar to tooltips and provide the same kind of APIs:

### Component

```hbs
<DMenu @ICON="plus" @Label={{i18n "foo.bar"}}>
  <ul>
    <li>Foo</li>
    <li>Bat</li>
    <li>Baz</li>
  </ul>
</DMenu>
```

They also support blocks:

```hbs
<DMenu>
  <:trigger>
    {{d-icon "plus"}}
    <span>{{i18n "foo.bar"}}</span>
  </:trigger>
  <:content>
    <ul>
      <li>Foo</li>
      <li>Bat</li>
      <li>Baz</li>
    </ul>
  </:content>
</DMenu>
```

### Service

You can manually show a menu using the `menu` service:

```javascript
const menuInstance = await this.menu.show(
  document.querySelector(".my-span"),
  options
)

// and later manual close or destroy it
menuInstance.close();
menuInstance.destroy();

// you can also just close any open tooltip through the service
this.menu.close();
```

The service also allows you to register event listeners on a trigger, it removes the need for you to manage open/close of a tooltip started through the service:

```javascript
const menuInstance = this.menu.register(
   document.querySelector(".my-span"),
   options
)

// when done you can destroy the instance to remove the listeners
menuInstance.destroy();
```

Note that the service also allows you to use a custom component as content which will receive `@data` and `@close` as args:

```javascript
const menuInstance = await this.menu.show(
  document.querySelector(".my-span"),
  { 
    component: MyComponent,
    data: { foo: 1 }
  }
)
```


## Toasts

Interacting with toasts is made only through the `toasts` service.

A default component is provided (DDefaultToast) and can be used through dedicated service methods:

- this.toasts.success({ ... });
- this.toasts.warning({ ... });
- this.toasts.info({ ... });
- this.toasts.error({ ... });
- this.toasts.default({ ... });

```javascript
this.toasts.success({
  data: {
    title: "Foo",
    message: "Bar",
    actions: [
      {
        label: "Ok",
        class: "btn-primary",
        action: (componentArgs) => {
          // eslint-disable-next-line no-alert
          alert("Closing toast:" + componentArgs.data.title);
          componentArgs.close();
        },
      }
    ]
  },
});
```

You can also provide your own component:

```javascript
this.toasts.show(MyComponent, {
  autoClose: false,
  class: "foo",
  data: { baz: 1 },
})
```

Co-authored-by: Martin Brennan <mjrbrennan@gmail.com>
Co-authored-by: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com>
Co-authored-by: David Taylor <david@taylorhq.com>
Co-authored-by: Jarek Radosz <jradosz@gmail.com>
2023-09-26 13:39:52 +02:00

241 lines
4.3 KiB
SCSS

.chat-message-text.-deleted,
.chat-message-text.-hidden {
margin-left: calc(var(--message-left-width) + 0.75em);
padding: 0;
.chat-message-expand {
color: var(--primary-low-mid);
padding: 0.25em;
.d-button-label {
text-align: left;
}
&:hover {
background: inherit;
color: inherit;
}
}
}
.chat-message-reaction {
> * {
pointer-events: none;
}
}
[data-content][data-identifier="chat-message-reaction-tooltip"] {
font-size: var(--font-down-1);
.emoji {
padding-left: 0.5rem;
}
}
.chat-message {
align-items: flex-start;
padding: 0.25em 0.5em 0.25em 0.75em;
display: flex;
min-width: 0;
.chat-message-reaction {
@include chat-reaction;
will-change: scale;
&:active {
transform: scale(0.93);
}
}
.chat-message-content {
display: flex;
flex-direction: column;
flex-grow: 1;
word-break: break-word;
overflow-wrap: break-word;
min-width: 0;
}
.chat-message-text {
min-width: 0;
width: 100%;
code {
box-sizing: border-box;
font-size: var(--font-down-1);
width: 100%;
}
.mention.highlighted {
background: var(--tertiary-low);
color: var(--primary);
display: inline-block;
font-size: 0.93em;
font-weight: normal;
padding: 0 0.3em 0.07em;
border-radius: 0.6em;
text-decoration: none;
}
// Automatic aspect-ratio mapping https://developer.mozilla.org/en-US/docs/Web/Media/images/aspect_ratio_mapping
p img:not(.emoji) {
max-width: 100%;
height: auto;
}
ul,
ol {
padding-left: 1.25em;
}
}
.chat-message-edited {
display: inline-block;
color: var(--primary-medium);
font-size: var(--font-down-2);
}
.chat-message-reaction-list,
.chat-transcript-reactions {
@include unselectable;
margin-top: 0.25em;
display: flex;
flex-wrap: wrap;
.chat-message-react-btn {
vertical-align: top;
padding: 0em 0.25em;
background: none;
border: none;
will-change: scale;
&:active {
transform: scale(0.93);
}
> * {
pointer-events: none;
}
.d-icon {
color: var(--primary-high);
}
&:hover {
.d-icon {
color: var(--primary);
}
}
}
}
.chat-message-avatar .chat-user-avatar .chat-user-avatar__container .avatar,
.chat-emoji-avatar .chat-emoji-avatar-container {
width: 28px;
height: 28px;
}
}
.touch .chat-message-container {
&.-active {
background: var(--d-hover);
border-radius: var(--d-border-radius);
&.-bookmarked {
background: var(--highlight-low);
}
}
}
.no-touch .chat-message-container {
&:hover,
&.-active {
background: var(--d-hover);
}
&:hover {
.chat-message-reaction-list .chat-message-react-btn {
display: inline-block;
}
}
&.-active,
&:hover {
&.-bookmarked {
background: var(--highlight-medium);
}
&.-deleted {
background-color: var(--danger-medium);
}
&.-highlighted {
background-color: var(--tertiary-medium);
}
}
}
.chat-message-container {
background-color: var(--d-content-background, var(--secondary));
&.-errored {
color: var(--primary-medium);
}
&.-deleted {
background-color: var(--danger-low);
padding-block: 0.25rem;
}
&.-bookmarked {
background: var(--highlight-bg);
}
&.-highlighted {
background-color: var(--tertiary-low);
}
&.has-reply {
.chat-message {
display: grid;
grid-template-columns: var(--message-left-width) 1fr;
grid-template-rows: 30px auto;
grid-template-areas:
"replyto replyto"
"avatar message";
.chat-user-avatar {
grid-area: avatar;
}
.chat-message-content {
grid-area: message;
}
}
}
&.has-thread-indicator {
.chat-message {
display: grid;
grid-template-columns: var(--message-left-width) 1fr;
grid-template-rows: auto;
grid-template-areas:
"avatar message"
"threadindicator threadindicator";
padding-bottom: 0.65rem !important;
.chat-user-avatar {
grid-area: avatar;
}
.chat-message-content {
grid-area: message;
}
}
}
.chat-message-reaction-list .chat-message-react-btn {
display: none;
}
}