Skip to content

Commit

Permalink
[Breakout Rooms] UI and UX improvements (#235)
Browse files Browse the repository at this point in the history
* Fix UI on empty state button

* Fix list of validations to always show missing steps

* Improve style in validations

* Make copy in user(s) splitting block dynamic

* Update 'Waiting room' copy on user selection dropdown

* UI and copy fixes in Room block

* Button size adjusted in waiting room

* Improve copy and UI for frame selection

* Fix rooms container height

* Fix copy

* Increase timer limit and add +5min option

* CSS fixes

* Remove CSS nesting

* Update toast copy

* Update examples/breakout-rooms/src/components/BreakoutManager/BreakoutManager.tsx

Co-authored-by: Mettin Parzinski <[email protected]>

* Update examples/breakout-rooms/src/components/BreakoutManager/BreakoutManager.tsx

Co-authored-by: Mettin Parzinski <[email protected]>

* Update examples/breakout-rooms/src/components/RoomConfig/RoomConfig.tsx

Co-authored-by: Frederico Estrela <[email protected]>

* Iterate frame title rendering when set to room

* Update styles

* Update relative timer rendering to change timer button text
Update finish session button variant

* Improve styles and dropdown separator

* One more style fix

* One more more style fix

* Update examples/breakout-rooms/src/components/BreakoutManager/BreakoutManager.tsx

Co-authored-by: Mettin Parzinski <[email protected]>

* Fix broken copy

* Add CSS class to avoid li+li

---------

Co-authored-by: Mettin Parzinski <[email protected]>
Co-authored-by: Frederico Estrela <[email protected]>
  • Loading branch information
3 people authored and Daniel Fosco committed Jan 24, 2024
1 parent c6002d2 commit fc40e75
Show file tree
Hide file tree
Showing 17 changed files with 187 additions and 99 deletions.
6 changes: 3 additions & 3 deletions examples/breakout-rooms/src/components/Avatar/Avatar.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
.avatar {
border-radius: 100%;
flex-shrink: 0;
background: #817f99;
background: var(--indigo600);
box-shadow: 0 0 0 6px var(--color, transparent);
outline: 4px solid #fff;
outline: 4px solid var(--white);
width: 2.2em;
height: 2.2em;
font-size: 14px;
color: #fff;
color: var(--white);
display: flex;
justify-content: center;
align-items: center;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,48 @@
display: flex;
height: 100%;
flex-direction: column;
gap: 1em;
gap: var(--space-small);
}

.validation-messages {
background: #f5f5f3;
padding: 1em;
background: var(--indigo50);
border-radius: var(--border-radius-medium);
padding: var(--space-medium);
}

.validation-messages .validatino-messages-title {
.validation-messages .validation-messages-title {
font-size: 1em;
font-weight: 600;
line-height: 1em;
line-height: var(--space-small);
margin: 0;
color: #656b81;
color: var(--indigo600);
}

.validation-messages .validatino-messages-items {
.validation-messages .validation-messages-list {
font-size: 0.9em;
padding-left: var(--space-small);
margin-bottom: 0;
}

.validation-messages-item + .validation-messages-item {
margin-top: var(--space-xsmall);
}

.validation-messages-item::marker {
color: var(--indigo500);
padding-left: var(--space-small);
}

.toolbar {
display: flex;
flex-direction: column;
justify-content: center;
gap: 1em;
gap: var(--space-small);
}

.toolbar button {
justify-content: center;
margin: 0;
width: 100%;
padding: 1em;
padding: var(--space-small);
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ export const BreakoutManager: React.FC = () => {
if (frame) {
await service.setRoomTarget(selectedRoom, frame.id);
await miro.board.notifications.showInfo(
`Frame "${frame.title}" has been selected as starting point.`,
`${frame.title} is set as starting point for the room`,
);
await miro.board.deselect({ id: frame.id });
setSelectedRoom(undefined);
} else {
await miro.board.notifications.showError(
"We only support frames as starting point for now",
"Only frames are supported as starting point for rooms",
);
}
};
Expand All @@ -87,7 +87,7 @@ export const BreakoutManager: React.FC = () => {
const handleNudge = async (currentUser?: Json) => {
if (isUser(currentUser)) {
await miro.board.notifications.showInfo(
`<strong>${currentUser?.name}</strong> is waiting to start the session`,
`<strong>${currentUser?.name}</strong> is waiting for you to start the session`,
);
}
};
Expand All @@ -111,7 +111,7 @@ export const BreakoutManager: React.FC = () => {
setSelectedRoom(selected);

await miro.board.notifications.showInfo(
`Select the frame in the board for ${selected.name}`,
`Set a frame to the room by clicking on the frame title`,
);
};

Expand Down Expand Up @@ -187,25 +187,31 @@ export const BreakoutManager: React.FC = () => {
});
};

const valRooms = "Add rooms to your session";
const valUsers = "Add users to each room";
const valFrames = "Set a frame to each room";

const validations: string[] = [];
if (!breakout?.rooms.length) {
validations.push("Add rooms to your session");
validations.push(valRooms);
validations.push(valUsers);
validations.push(valFrames);
}

const allRoomsWithParticipants = breakout?.rooms.every(
(room) => room.participants.length > 0,
);

if (!allRoomsWithParticipants) {
validations.push("Add users to each room");
if (!allRoomsWithParticipants && !validations.includes(valUsers)) {
validations.push(valUsers);
}

const allRoomsWithTargets = breakout?.rooms.every((room) =>
Boolean(room.targetId),
);

if (!allRoomsWithTargets) {
validations.push("Set a frame to each room");
if (!allRoomsWithTargets && !validations.includes(valFrames)) {
validations.push(valFrames);
}

const canStartSession = validations.length < 1;
Expand Down Expand Up @@ -243,12 +249,14 @@ export const BreakoutManager: React.FC = () => {

{isEditable && validations.length > 0 ? (
<div className="validation-messages">
<h5 className="validatino-messages-title">
<h5 className="validation-messages-title">
Before starting the session:
</h5>
<ul className="validatino-messages-items">
<ul className="validation-messages-list">
{validations.map((message) => (
<li key={message}>{message}</li>
<li className="validation-messages-item" key={message}>
{message}
</li>
))}
</ul>
</div>
Expand All @@ -257,10 +265,10 @@ export const BreakoutManager: React.FC = () => {
{breakout?.state === "started" ? (
<Button
onClick={() => handleStopSession()}
variant="solid-danger"
variant="outline-danger"
size="x-large"
>
Stop session
Finish session
{canUseTimer && timer.state === "started"
? ` (${formatDisplayTime(timer.restDuration)})`
: null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,46 @@
}

.starter-action {
background: #f2f4fc;
border-radius: 0.25em;
padding: 1em;
background: var(--blue300);
border: none;
border-radius: var(--border-radius-medium);
cursor: default;
display: flex;
gap: 1em;
padding: var(--space-small);
gap: var(--space-small);
align-items: center;
align-self: flex-start;
width: 100%;
}

.starter-action .starter-action-title {
font-size: 1em;
font-size: 1.25em;
font-weight: 600;
line-height: 1.5em;
text-align: left;
color: #3859ff;
color: var(--blue700);
margin: 0;
}

.starter-action:hover {
background: var(--blue400);
cursor: pointer;
}

.starter-action:hover .starter-action-title {
color: var(--blue900);
}

.starter-action:hover .rounded-plus {
background-color: var(--blue900);
}

.rounded-plus {
border-radius: var(--border-radius-circle);
background-color: var(--blue700);
padding: var(--space-xsmall);
}

.rounded-plus svg {
color: var(--white);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IconButton, IconPlus } from "@mirohq/design-system";
import { IconPlus } from "@mirohq/design-system";
import React from "react";

import { WaitingIcon } from "../WaitingIcon";
Expand All @@ -12,17 +12,12 @@ type Props = {
export const BreakoutStarter: React.FC<Props> = ({ onAddGroup }) => {
return (
<section className="breakout-starter">
<div className="starter-action">
<IconButton
label="Add a room"
variant="solid-prominent"
css={{ borderRadius: "100%" }}
onClick={onAddGroup}
>
<button onClick={onAddGroup} className="starter-action">
<div className="rounded-plus">
<IconPlus />
</IconButton>
</div>
<h5 className="starter-action-title">Create a room to get started</h5>
</div>
</button>

<WaitingIcon />
</section>
Expand Down
16 changes: 10 additions & 6 deletions examples/breakout-rooms/src/components/RoomConfig/RoomConfig.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
display: flex;
flex-direction: column;
justify-content: center;
background: #eeeded;
border-radius: 0.25em;
background: var(--indigo50);
border-radius: var(--border-radius-medium);
gap: 0.5em;
padding: 1em;
padding: var(--space-small);
padding-top: var(--space-xsmall);
width: 100%;
height: 8em;
}

.room-controls {
Expand Down Expand Up @@ -43,20 +43,24 @@
.users .list {
/** Overrides DS specific tokens for dropdown **/
--space-inset-100: 16px;
font-size: 12px;
}

.users .list .separator {
margin: var(--space-xsmall) var(--space-xxsmall);
}

.users .list .item {
display: flex;
align-items: center;
gap: 1em;
gap: var(--space-small);
}
.users .list .item + div {
padding-left: 3.5em;
}

.avatars {
display: flex;
padding-left: var(--space-xxsmall);
}

.avatars .avatar:not(:first-child) {
Expand Down
36 changes: 29 additions & 7 deletions examples/breakout-rooms/src/components/RoomConfig/RoomConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
IconTrash,
IconUserAdd,
} from "@mirohq/design-system";
import { OnlineUserInfo } from "@mirohq/websdk-types";
import { Frame, OnlineUserInfo } from "@mirohq/websdk-types";

import type { Participant, Room } from "../../types";
import { Avatar } from "../Avatar";
Expand All @@ -35,23 +35,45 @@ export const RoomConfig: React.FunctionComponent<Props> = ({
onAddParticipant,
onRemoveParticipant,
}) => {
const [title, setName] = React.useState("");
React.useEffect(() => {
async function FetchFrame(): Promise<void> {
if (!room.targetId) {
return;
}
const frame = (await miro.board.getById(room.targetId)) as Frame;
setName(frame?.title);
}
FetchFrame();
}, [room.targetId]);

const renderedTitle = title ? `${title}` : "frame";
const dropdownSeparator = (
<div className="separator">
<DropdownMenu.Separator />
</div>
);
return (
<div key={room.id} className="room">
<div className="room-controls">
<h3 className="room-controls-title" title={room.name}>
{room.name}
</h3>
<IconButton
label="Select frame"
variant="ghost"
label={
room.targetId
? `Room is set to ${renderedTitle}`
: "Set frame to room"
}
variant={room.targetId ? "outline" : "ghost"}
disabled={!isEditable}
onClick={() => onSelectTarget(room)}
>
<IconFrame />
</IconButton>

<IconButton
label="Remove frame"
label="Remove room"
variant="ghost"
disabled={!isEditable}
onClick={() => onRemove(room)}
Expand All @@ -72,7 +94,7 @@ export const RoomConfig: React.FunctionComponent<Props> = ({
<DropdownMenu>
<DropdownMenu.Trigger asChild>
<IconButton
label="Assign participant"
label="Add user"
variant="outline"
css={{ borderRadius: "100%" }}
>
Expand All @@ -88,7 +110,7 @@ export const RoomConfig: React.FunctionComponent<Props> = ({
{unassignedUsers.length ? (
<div className="list">
<DropdownMenu.Item disabled>
Users not in the room
Users not in rooms
</DropdownMenu.Item>
{unassignedUsers.map((user) => (
<DropdownMenu.Item
Expand All @@ -107,7 +129,7 @@ export const RoomConfig: React.FunctionComponent<Props> = ({

{room.participants.length ? (
<div className="list">
{unassignedUsers.length ? <DropdownMenu.Separator /> : null}
{unassignedUsers.length ? dropdownSeparator : null}
{room.participants.map((user) => (
<DropdownMenu.Item
key={user.id}
Expand Down
Loading

0 comments on commit fc40e75

Please sign in to comment.