Merge pull request #5761 from matrix-org/t3chguy/spaces4.8

Iterate space panel visually and functionally
This commit is contained in:
Michael Telatynski 2021-03-16 17:41:14 +00:00 committed by GitHub
commit 0ce78f469f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 54 deletions

View file

@ -16,9 +16,8 @@ limitations under the License.
$topLevelHeight: 32px; $topLevelHeight: 32px;
$nestedHeight: 24px; $nestedHeight: 24px;
$gutterSize: 17px; $gutterSize: 16px;
$activeStripeSize: 4px; $activeBorderTransparentGap: 1px;
$activeBorderTransparentGap: 2px;
$activeBackgroundColor: $roomtile-selected-bg-color; $activeBackgroundColor: $roomtile-selected-bg-color;
$activeBorderColor: $secondary-fg-color; $activeBorderColor: $secondary-fg-color;
@ -36,6 +35,7 @@ $activeBorderColor: $secondary-fg-color;
.mx_SpacePanel_spaceTreeWrapper { .mx_SpacePanel_spaceTreeWrapper {
flex: 1; flex: 1;
overflow-y: scroll;
} }
.mx_SpacePanel_toggleCollapse { .mx_SpacePanel_toggleCollapse {
@ -63,21 +63,26 @@ $activeBorderColor: $secondary-fg-color;
} }
.mx_AutoHideScrollbar { .mx_AutoHideScrollbar {
padding: 16px 12px 16px 0; padding: 16px 0;
} }
.mx_SpaceButton_toggleCollapse { .mx_SpaceButton_toggleCollapse {
cursor: pointer; cursor: pointer;
} }
.mx_SpaceItem.collapsed { .mx_SpaceTreeLevel {
.mx_SpaceButton { display: flex;
.mx_NotificationBadge { flex-direction: column;
right: -4px; max-width: 250px;
top: -4px; flex-grow: 1;
} }
}
.mx_SpaceItem {
display: inline-flex;
flex-flow: wrap;
}
.mx_SpaceItem.collapsed {
& > .mx_SpaceButton > .mx_SpaceButton_toggleCollapse { & > .mx_SpaceButton > .mx_SpaceButton_toggleCollapse {
transform: rotate(-90deg); transform: rotate(-90deg);
} }
@ -89,34 +94,43 @@ $activeBorderColor: $secondary-fg-color;
.mx_SpaceItem:not(.hasSubSpaces) > .mx_SpaceButton { .mx_SpaceItem:not(.hasSubSpaces) > .mx_SpaceButton {
margin-left: $gutterSize; margin-left: $gutterSize;
min-width: 40px;
} }
.mx_SpaceButton { .mx_SpaceButton {
border-radius: 8px; border-radius: 8px;
position: relative;
margin-bottom: 2px; margin-bottom: 2px;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 4px; padding: 4px 4px 4px 0;
width: 100%;
&.mx_SpaceButton_active { &.mx_SpaceButton_active {
&:not(.mx_SpaceButton_narrow) .mx_SpaceButton_selectionWrapper { &:not(.mx_SpaceButton_narrow) .mx_SpaceButton_selectionWrapper {
background-color: $activeBackgroundColor; background-color: $activeBackgroundColor;
border-radius: 8px;
} }
&.mx_SpaceButton_narrow { &.mx_SpaceButton_narrow .mx_SpaceButton_selectionWrapper {
.mx_BaseAvatar, .mx_SpaceButton_avatarPlaceholder { padding: $activeBorderTransparentGap;
border: 2px $activeBorderColor solid; border: 3px $activeBorderColor solid;
border-radius: 11px;
}
} }
} }
.mx_SpaceButton_selectionWrapper { .mx_SpaceButton_selectionWrapper {
position: relative;
display: flex; display: flex;
flex: 1; flex: 1;
align-items: center; align-items: center;
border-radius: 12px;
padding: 4px;
}
&:not(.mx_SpaceButton_narrow) {
.mx_SpaceButton_selectionWrapper {
width: 100%;
padding-right: 16px;
overflow: hidden;
}
} }
.mx_SpaceButton_name { .mx_SpaceButton_name {
@ -124,7 +138,6 @@ $activeBorderColor: $secondary-fg-color;
margin-left: 8px; margin-left: 8px;
white-space: nowrap; white-space: nowrap;
display: block; display: block;
max-width: 150px;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
padding-right: 8px; padding-right: 8px;
@ -133,8 +146,10 @@ $activeBorderColor: $secondary-fg-color;
} }
.mx_SpaceButton_toggleCollapse { .mx_SpaceButton_toggleCollapse {
width: calc($gutterSize - $activeStripeSize); width: $gutterSize;
margin-left: 1px; // negative margin to place it correctly even with the complex
// 4px selection border each space button has when active
margin-right: -4px;
height: 20px; height: 20px;
mask-position: center; mask-position: center;
mask-size: 20px; mask-size: 20px;
@ -172,11 +187,6 @@ $activeBorderColor: $secondary-fg-color;
} }
} }
.mx_SpaceButton_avatarPlaceholder {
border: $activeBorderTransparentGap transparent solid;
padding: $activeBorderTransparentGap;
}
&.mx_SpaceButton_new .mx_SpaceButton_icon { &.mx_SpaceButton_new .mx_SpaceButton_icon {
background-color: $accent-color; background-color: $accent-color;
transition: all .1s ease-in-out; // TODO transition transition: all .1s ease-in-out; // TODO transition
@ -196,21 +206,8 @@ $activeBorderColor: $secondary-fg-color;
} }
} }
.mx_BaseAvatar { .mx_BaseAvatar_image {
/* moving the border-radius to this element from _image border-radius: 8px;
element so we can add a border to it without the initials being displaced */
overflow: hidden;
border: 2px transparent solid;
padding: $activeBorderTransparentGap;
.mx_BaseAvatar_initial {
top: $activeBorderTransparentGap;
left: $activeBorderTransparentGap;
}
.mx_BaseAvatar_image {
border-radius: 8px;
}
} }
.mx_SpaceButton_menuButton { .mx_SpaceButton_menuButton {
@ -219,8 +216,9 @@ $activeBorderColor: $secondary-fg-color;
height: 20px; height: 20px;
margin-top: auto; margin-top: auto;
margin-bottom: auto; margin-bottom: auto;
position: relative;
display: none; display: none;
position: absolute;
right: 4px;
&::before { &::before {
top: 2px; top: 2px;
@ -239,9 +237,8 @@ $activeBorderColor: $secondary-fg-color;
} }
.mx_SpacePanel_badgeContainer { .mx_SpacePanel_badgeContainer {
position: absolute;
height: 16px; height: 16px;
// don't set width so that it takes no space when there is no badge to show
margin: auto 0; // vertically align
// Create a flexbox to make aligning dot badges easier // Create a flexbox to make aligning dot badges easier
display: flex; display: flex;
@ -261,14 +258,25 @@ $activeBorderColor: $secondary-fg-color;
&.collapsed { &.collapsed {
.mx_SpaceButton { .mx_SpaceButton {
.mx_SpacePanel_badgeContainer { .mx_SpacePanel_badgeContainer {
position: absolute; right: -3px;
right: 0px; top: -3px;
top: 2px; }
&.mx_SpaceButton_active .mx_SpacePanel_badgeContainer {
// when we draw the selection border we move the relative bounds of our parent
// so update our position within the bounds of the parent to maintain position overall
right: -6px;
top: -6px;
} }
} }
} }
&:not(.collapsed) { &:not(.collapsed) {
.mx_SpacePanel_badgeContainer {
position: absolute;
right: 4px;
}
.mx_SpaceButton:hover, .mx_SpaceButton:hover,
.mx_SpaceButton:focus-within, .mx_SpaceButton:focus-within,
.mx_SpaceButton_hasMenuOpen { .mx_SpaceButton_hasMenuOpen {

View file

@ -132,6 +132,7 @@ limitations under the License.
height: min-content; height: min-content;
margin-left: auto; margin-left: auto;
margin-right: 16px; margin-right: 16px;
display: inline-flex;
} }
} }

View file

@ -51,6 +51,7 @@ interface IItemProps {
isNested?: boolean; isNested?: boolean;
isPanelCollapsed?: boolean; isPanelCollapsed?: boolean;
onExpand?: Function; onExpand?: Function;
parents?: Set<string>;
} }
interface IItemState { interface IItemState {
@ -299,7 +300,8 @@ export class SpaceItem extends React.PureComponent<IItemProps, IItemState> {
const isNarrow = this.props.isPanelCollapsed; const isNarrow = this.props.isPanelCollapsed;
const collapsed = this.state.collapsed || forceCollapsed; const collapsed = this.state.collapsed || forceCollapsed;
const childSpaces = SpaceStore.instance.getChildSpaces(space.roomId); const childSpaces = SpaceStore.instance.getChildSpaces(space.roomId)
.filter(s => !this.props.parents?.has(s.roomId));
const isActive = activeSpaces.includes(space); const isActive = activeSpaces.includes(space);
const itemClasses = classNames({ const itemClasses = classNames({
"mx_SpaceItem": true, "mx_SpaceItem": true,
@ -312,11 +314,17 @@ export class SpaceItem extends React.PureComponent<IItemProps, IItemState> {
mx_SpaceButton_narrow: isNarrow, mx_SpaceButton_narrow: isNarrow,
}); });
const notificationState = SpaceStore.instance.getNotificationState(space.roomId); const notificationState = SpaceStore.instance.getNotificationState(space.roomId);
const childItems = childSpaces && !collapsed ? <SpaceTreeLevel
spaces={childSpaces} let childItems;
activeSpaces={activeSpaces} if (childSpaces && !collapsed) {
isNested={true} childItems = <SpaceTreeLevel
/> : null; spaces={childSpaces}
activeSpaces={activeSpaces}
isNested={true}
parents={new Set(this.props.parents).add(this.props.space.roomId)}
/>;
}
let notifBadge; let notifBadge;
if (notificationState) { if (notificationState) {
notifBadge = <div className="mx_SpacePanel_badgeContainer"> notifBadge = <div className="mx_SpacePanel_badgeContainer">
@ -383,12 +391,14 @@ interface ITreeLevelProps {
spaces: Room[]; spaces: Room[];
activeSpaces: Room[]; activeSpaces: Room[];
isNested?: boolean; isNested?: boolean;
parents: Set<string>;
} }
const SpaceTreeLevel: React.FC<ITreeLevelProps> = ({ const SpaceTreeLevel: React.FC<ITreeLevelProps> = ({
spaces, spaces,
activeSpaces, activeSpaces,
isNested, isNested,
parents,
}) => { }) => {
return <ul className="mx_SpaceTreeLevel"> return <ul className="mx_SpaceTreeLevel">
{spaces.map(s => { {spaces.map(s => {
@ -397,6 +407,7 @@ const SpaceTreeLevel: React.FC<ITreeLevelProps> = ({
activeSpaces={activeSpaces} activeSpaces={activeSpaces}
space={s} space={s}
isNested={isNested} isNested={isNested}
parents={parents}
/>); />);
})} })}
</ul>; </ul>;