Room list: edit or remove custom sections (#33283)
* feat(sc): add section menu to section header * feat(rls): add edit and remove sections * feat(dialog): add editing mode to CreateSectionDialog * feat(dialog): add remove section dialog * feat(vm): wire up vm and stores * test: update existing snapshots * test(e2e): add playwright tests to edit and remove a section * chore: fix remove section i18n key * fix: able to send empty sections * chore: update create section editing docs * chore: remove useless fallback * chore: add logs when section is unknown * feat: use different wording when removing an empty section * fix: only animate the chevron icon in the section header * fix: change dialog subtitle weight to medium
This commit is contained in:
@@ -147,6 +147,9 @@
|
||||
"room_options": "Room Options",
|
||||
"section_created": "Section created",
|
||||
"section_header": {
|
||||
"edit_section": "Edit section",
|
||||
"more_options": "More options",
|
||||
"remove_section": "Remove section",
|
||||
"toggle": "Toggle %(section)s section",
|
||||
"toggle_unread": "Toggle %(section)s section with unread room(s)"
|
||||
},
|
||||
|
||||
+88
-64
@@ -8376,24 +8376,30 @@ exports[`<RoomListView /> > renders LargeSectionList story 1`] = `
|
||||
>
|
||||
<div
|
||||
class="Flex-module_flex RoomListSectionHeaderView-module_container"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<svg
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<div
|
||||
class="Flex-module_flex"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Favourites
|
||||
</span>
|
||||
<svg
|
||||
class="RoomListSectionHeaderView-module_chevron"
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Favourites
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
@@ -11528,24 +11534,30 @@ exports[`<RoomListView /> > renders LargeSectionList story 1`] = `
|
||||
>
|
||||
<div
|
||||
class="Flex-module_flex RoomListSectionHeaderView-module_container"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<svg
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<div
|
||||
class="Flex-module_flex"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Chats
|
||||
</span>
|
||||
<svg
|
||||
class="RoomListSectionHeaderView-module_chevron"
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Chats
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
@@ -13693,24 +13705,30 @@ exports[`<RoomListView /> > renders SmallSectionList story 1`] = `
|
||||
>
|
||||
<div
|
||||
class="Flex-module_flex RoomListSectionHeaderView-module_container"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<svg
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<div
|
||||
class="Flex-module_flex"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Favourites
|
||||
</span>
|
||||
<svg
|
||||
class="RoomListSectionHeaderView-module_chevron"
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Favourites
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
@@ -14020,24 +14038,30 @@ exports[`<RoomListView /> > renders SmallSectionList story 1`] = `
|
||||
>
|
||||
<div
|
||||
class="Flex-module_flex RoomListSectionHeaderView-module_container"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<svg
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<div
|
||||
class="Flex-module_flex"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Chats
|
||||
</span>
|
||||
<svg
|
||||
class="RoomListSectionHeaderView-module_chevron"
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Chats
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
+17
-4
@@ -19,7 +19,8 @@
|
||||
background-color: var(--cpd-color-bg-canvas-default);
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
&:focus-visible,
|
||||
&:has(button[data-state="open"]) {
|
||||
color: var(--cpd-color-text-primary);
|
||||
|
||||
svg {
|
||||
@@ -29,20 +30,24 @@
|
||||
.container {
|
||||
background-color: var(--cpd-color-bg-action-tertiary-hovered);
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
.chevron {
|
||||
transition: transform 0.05s linear;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
svg {
|
||||
.chevron {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
&[aria-expanded="true"] {
|
||||
svg {
|
||||
.chevron {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
@@ -58,6 +63,10 @@
|
||||
padding: var(--cpd-space-1-5x) var(--cpd-space-2x) var(--cpd-space-1-5x) var(--cpd-space-1x);
|
||||
border-radius: 8px;
|
||||
|
||||
div {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -77,3 +86,7 @@
|
||||
.lastHeader {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
+6
-1
@@ -25,6 +25,8 @@ type RoomListSectionHeaderProps = RoomListSectionHeaderViewSnapshot &
|
||||
const RoomListSectionHeaderViewWrapperImpl = ({
|
||||
onClick,
|
||||
onFocus,
|
||||
editSection,
|
||||
removeSection,
|
||||
isFocused,
|
||||
sectionIndex,
|
||||
sectionCount,
|
||||
@@ -32,7 +34,7 @@ const RoomListSectionHeaderViewWrapperImpl = ({
|
||||
roomCountInSection,
|
||||
...rest
|
||||
}: RoomListSectionHeaderProps): JSX.Element => {
|
||||
const vm = useMockedViewModel(rest, { onClick });
|
||||
const vm = useMockedViewModel(rest, { onClick, editSection, removeSection });
|
||||
return (
|
||||
<RoomListSectionHeaderView
|
||||
vm={vm}
|
||||
@@ -57,8 +59,11 @@ const meta = {
|
||||
isExpanded: true,
|
||||
isFocused: false,
|
||||
isUnread: false,
|
||||
displaySectionMenu: true,
|
||||
onClick: fn(),
|
||||
onFocus: fn(),
|
||||
editSection: fn(),
|
||||
removeSection: fn(),
|
||||
sectionIndex: 1,
|
||||
sectionCount: 3,
|
||||
roomCountInSection: 5,
|
||||
|
||||
+78
-5
@@ -5,15 +5,18 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { memo, type JSX, type FocusEvent, type MouseEventHandler } from "react";
|
||||
import React, { memo, type JSX, type FocusEvent, type MouseEventHandler, useState } from "react";
|
||||
import ChevronRightIcon from "@vector-im/compound-design-tokens/assets/web/icons/chevron-right";
|
||||
import classNames from "classnames";
|
||||
import { IconButton, Menu, MenuItem } from "@vector-im/compound-web";
|
||||
import { OverflowHorizontalIcon, EditIcon, DeleteIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { useViewModel, type ViewModel } from "../../../core/viewmodel";
|
||||
import styles from "./RoomListSectionHeaderView.module.css";
|
||||
import { Flex } from "../../../core/utils/Flex";
|
||||
import { useI18n } from "../../../core/i18n/i18nContext";
|
||||
import { getGroupHeaderAccessibleProps } from "../../../core/VirtualizedList";
|
||||
import { _t } from "../../../core/i18n/i18n";
|
||||
|
||||
/**
|
||||
* The observable state snapshot for a room list section header.
|
||||
@@ -27,6 +30,8 @@ export interface RoomListSectionHeaderViewSnapshot {
|
||||
isExpanded: boolean;
|
||||
/** Whether the section is unread (has any unread rooms) */
|
||||
isUnread: boolean;
|
||||
/** Wether to display the section menu */
|
||||
displaySectionMenu: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,6 +40,10 @@ export interface RoomListSectionHeaderViewSnapshot {
|
||||
export interface RoomListSectionHeaderActions {
|
||||
/** Handler invoked when the section header is clicked (toggles expand/collapse). */
|
||||
onClick: MouseEventHandler<HTMLButtonElement>;
|
||||
/** Handler invoked when the edit section button is clicked */
|
||||
editSection: () => void;
|
||||
/** Handler invoked when the remove section button is clicked */
|
||||
removeSection: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +100,7 @@ export const RoomListSectionHeaderView = memo(function RoomListSectionHeaderView
|
||||
roomCountInSection,
|
||||
}: Readonly<RoomListSectionHeaderViewProps>): JSX.Element {
|
||||
const { translate: _t } = useI18n();
|
||||
const { id, title, isExpanded, isUnread } = useViewModel(vm);
|
||||
const { id, title, isExpanded, isUnread, displaySectionMenu } = useViewModel(vm);
|
||||
const isLastSection = sectionIndex === sectionCount - 1;
|
||||
|
||||
return (
|
||||
@@ -118,11 +127,75 @@ export const RoomListSectionHeaderView = memo(function RoomListSectionHeaderView
|
||||
: _t("room_list|section_header|toggle", { section: title })
|
||||
}
|
||||
>
|
||||
<Flex className={styles.container} align="center" gap="var(--cpd-space-0-5x)">
|
||||
<ChevronRightIcon width="24px" height="24px" fill="var(--cpd-color-icon-secondary)" />
|
||||
<span className={styles.title}>{title}</span>
|
||||
<Flex className={styles.container} align="center" justify="space-between" gap="var(--cpd-space-2x)">
|
||||
<Flex align="center" gap="var(--cpd-space-0-5x)">
|
||||
<ChevronRightIcon
|
||||
className={styles.chevron}
|
||||
width="24px"
|
||||
height="24px"
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
/>
|
||||
<span className={styles.title}>{title}</span>
|
||||
</Flex>
|
||||
{displaySectionMenu && <MenuComponent vm={vm} />}
|
||||
</Flex>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
interface MenuComponentProps {
|
||||
vm: RoomListSectionHeaderViewModel;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Menu component for the section header.
|
||||
*/
|
||||
|
||||
function MenuComponent({ vm }: MenuComponentProps): JSX.Element {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
title={_t("room_list|section_header|more_options")}
|
||||
showTitle={false}
|
||||
align="start"
|
||||
trigger={
|
||||
<IconButton
|
||||
className={styles.menu}
|
||||
tooltip={_t("room_list|section_header|more_options")}
|
||||
aria-label={_t("room_list|section_header|more_options")}
|
||||
size="24px"
|
||||
style={{ padding: "2px" }}
|
||||
color="var(--cpd-color-icon-primary)"
|
||||
>
|
||||
<OverflowHorizontalIcon fill="var(--cpd-color-icon-primary)" />
|
||||
</IconButton>
|
||||
}
|
||||
>
|
||||
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
|
||||
<div
|
||||
// We don't want keyboard navigation events to bubble up to the ListView changing the focused item
|
||||
onKeyDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
<MenuItem
|
||||
hideChevron={true}
|
||||
Icon={EditIcon}
|
||||
label={_t("room_list|section_header|edit_section")}
|
||||
onSelect={() => vm.editSection()}
|
||||
onClick={(evt) => evt.stopPropagation()}
|
||||
/>
|
||||
<MenuItem
|
||||
hideChevron={true}
|
||||
Icon={DeleteIcon}
|
||||
label={_t("room_list|section_header|remove_section")}
|
||||
onSelect={() => vm.removeSection()}
|
||||
onClick={(evt) => evt.stopPropagation()}
|
||||
/>
|
||||
</div>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
||||
+54
-15
@@ -24,24 +24,63 @@ exports[`<RoomListSectionHeaderView /> stories > renders Default story 1`] = `
|
||||
>
|
||||
<div
|
||||
class="Flex-module_flex RoomListSectionHeaderView-module_container"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: space-between; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<svg
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<div
|
||||
class="Flex-module_flex"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-0-5x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
<svg
|
||||
class="RoomListSectionHeaderView-module_chevron"
|
||||
fill="var(--cpd-color-icon-secondary)"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8.7 17.3a.95.95 0 0 1-.275-.7q0-.425.275-.7l3.9-3.9-3.9-3.9a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l4.6 4.6q.15.15.213.325.062.175.062.375t-.062.375a.9.9 0 0 1-.213.325l-4.6 4.6a.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="RoomListSectionHeaderView-module_title"
|
||||
>
|
||||
Favourites
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="menu"
|
||||
aria-label="More options"
|
||||
aria-labelledby="_r_2_"
|
||||
class="_icon-button_1215g_8 RoomListSectionHeaderView-module_menu"
|
||||
color="var(--cpd-color-icon-primary)"
|
||||
data-kind="primary"
|
||||
data-state="closed"
|
||||
id="radix-_r_0_"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 24px; padding: 2px;"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
Favourites
|
||||
</span>
|
||||
<div
|
||||
class="_indicator-icon_147l5_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
fill="var(--cpd-color-icon-primary)"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user