fix: accessibility and usability issues

pull/120/head
sualko 2021-01-23 11:36:59 +01:00
parent 7cd5b93df7
commit b238bf57c5
6 changed files with 96 additions and 64 deletions

View File

@ -98,8 +98,33 @@ pre {
opacity: 0; opacity: 0;
&.icon-visible { &.icon-visible {
opacity: 0.4;
}
}
.action-item {
border: 0;
background-color: transparent;
padding: 14px;
border-radius: 50%;
line-height: 0;
display: inline-block;
.icon {
opacity: 0.5; opacity: 0.5;
} }
&:hover {
background-color: var(--color-background-dark);
.icon {
opacity: 1;
&.icon-delete {
background-image: var(--icon-delete-e9322d);
}
}
}
} }
&, & > table { &, & > table {
@ -111,11 +136,9 @@ pre {
white-space: nowrap; white-space: nowrap;
} }
tr {
min-height: 62px;
}
th { th {
padding: 14px 6px;
border-bottom: 1px var(--color-background-darker) solid; border-bottom: 1px var(--color-background-darker) solid;
cursor: pointer; cursor: pointer;
@ -125,8 +148,8 @@ pre {
} }
} }
td, th { td {
padding: 10px; padding: 0 6px;
position: relative; position: relative;
display: table-cell; display: table-cell;
@ -149,43 +172,13 @@ pre {
} }
&.icon-col { &.icon-col {
width: 32px; width: 42px;
} padding: 0;
a.icon {
margin-left: 5px;
} }
} }
tr:hover { tfoot td {
.icon { padding: 14px 6px;
opacity: 0.5;
&:hover {
opacity: 1;
}
}
.action-rename {
&::after {
opacity: 0.5;
}
&:hover::after {
opacity: 1;
}
}
}
.copy-to-clipboard {
cursor: pointer;
border-radius: 50%;
width: 20px;
height: 20px;
&:active {
background-color: var(--color-success);
}
} }
.selected-row { .selected-row {
@ -204,6 +197,33 @@ pre {
width: 100%; width: 100%;
} }
} }
tbody tr {
td:first-child {
padding-left: 5px;
}
&:hover {
background-color: var(--color-background-hover);
box-shadow: 5px 0 0 var(--color-primary-element) inset;
.action-rename {
&::after {
opacity: 0.5;
}
&:hover::after {
opacity: 1;
}
}
}
}
.copy-to-clipboard {
&:active {
background-color: var(--color-success) !important;
}
}
} }
.bbb-form-element { .bbb-form-element {

View File

@ -13,9 +13,10 @@ const EditRoom: React.FC<Props> = ({ room, restriction, updateProperty }) => {
return ( return (
<> <>
<a className="icon icon-edit icon-visible" <button onClick={ev => { ev.preventDefault(), setOpen(true); }}
onClick={ev => { ev.preventDefault(), setOpen(true); }} title={t('bbb', 'Edit')} className="action-item">
title={t('bbb', 'Edit')} /> <span className="icon icon-edit icon-visible"></span>
</button>
<EditRoomDialog room={room} restriction={restriction} updateProperty={updateProperty} open={open} setOpen={setOpen} /> <EditRoomDialog room={room} restriction={restriction} updateProperty={updateProperty} open={open} setOpen={setOpen} />
</> </>

View File

@ -12,15 +12,21 @@ const RecordingRow: React.FC<Props> = ({recording, deleteRecording, storeRecordi
return ( return (
<tr key={recording.id}> <tr key={recording.id}>
<td className="start icon-col"> <td className="start icon-col">
<a href={recording.url} className="icon icon-external icon-visible" target="_blank" rel="noopener noreferrer"></a> <a href={recording.url} className="action-item" target="_blank" rel="noopener noreferrer">
<span className="icon icon-external icon-visible"></span>
</a>
</td> </td>
<td className="share icon-col"> <td className="share icon-col">
<CopyToClipboard text={recording.url}> <CopyToClipboard text={recording.url}>
<span className="icon icon-clippy icon-visible copy-to-clipboard" ></span> <button className="action-item copy-to-clipboard">
<span className="icon icon-clippy icon-visible" ></span>
</button>
</CopyToClipboard> </CopyToClipboard>
</td> </td>
<td className="icon-col"> <td className="icon-col">
<a onClick={() => storeRecording(recording)} className="icon icon-add-shortcut icon-visible"></a> <button className="action-item" onClick={() => storeRecording(recording)}>
<span className="icon icon-add-shortcut icon-visible"></span>
</button>
</td> </td>
<td> <td>
{(new Date(recording.startTime)).toLocaleString()} {(new Date(recording.startTime)).toLocaleString()}
@ -35,9 +41,9 @@ const RecordingRow: React.FC<Props> = ({recording, deleteRecording, storeRecordi
{recording.type} {recording.type}
</td> </td>
<td className="remove icon-col"> <td className="remove icon-col">
<a className="icon icon-delete icon-visible" <button className="action-item" onClick={() => deleteRecording(recording)} title={t('bbb', 'Delete')}>
onClick={() => deleteRecording(recording)} <span className="icon icon-delete icon-visible"></span>
title={t('bbb', 'Delete')} /> </button>
</td> </td>
</tr> </tr>
); );

View File

@ -187,15 +187,21 @@ const RoomRow: React.FC<Props> = (props) => {
<> <>
<tr className={showRecordings ? 'selected-row' : ''}> <tr className={showRecordings ? 'selected-row' : ''}>
<td className="start icon-col"> <td className="start icon-col">
<a href={api.getRoomUrl(room)} className="icon icon-play icon-visible" target="_blank" rel="noopener noreferrer"></a> <a href={api.getRoomUrl(room)} className="action-item" target="_blank" rel="noopener noreferrer">
<span className="icon icon-play icon-visible"></span>
</a>
</td> </td>
<td className="share icon-col"> <td className="share icon-col">
<CopyToClipboard text={api.getRoomUrl(room)}> <CopyToClipboard text={api.getRoomUrl(room)}>
<span className="icon icon-clippy icon-visible copy-to-clipboard" ></span> <button className="action-item copy-to-clipboard">
<span className="icon icon-clippy icon-visible" ></span>
</button>
</CopyToClipboard> </CopyToClipboard>
</td> </td>
<td className="store icon-col"> <td className="store icon-col">
<a onClick={() => storeRoom()} className="icon icon-add-shortcut icon-visible"></a> <button className="action-item" onClick={() => storeRoom()}>
<span className="icon icon-add-shortcut icon-visible"></span>
</button>
</td> </td>
<td className="name"> <td className="name">
{edit('name')} {edit('name')}
@ -219,9 +225,9 @@ const RoomRow: React.FC<Props> = (props) => {
<EditRoom room={props.room} restriction={props.restriction} updateProperty={updateRoom} /> <EditRoom room={props.room} restriction={props.restriction} updateProperty={updateRoom} />
</td> </td>
<td className="remove icon-col"> <td className="remove icon-col">
<a className="icon icon-delete icon-visible" <button className="action-item" onClick={deleteRow as any} title={t('bbb', 'Delete')}>
onClick={deleteRow as any} <span className="icon icon-delete icon-visible"></span>
title={t('bbb', 'Delete')} /> </button>
</td> </td>
</tr> </tr>
{showRecordings && <tr className="recordings-row"> {showRecordings && <tr className="recordings-row">

View File

@ -12,7 +12,7 @@
align-items: center; align-items: center;
&:hover { &:hover {
background-color: var(--color-background-dark); background-color: var(--color-background-hover);
} }
.avatardiv { .avatardiv {
@ -29,11 +29,6 @@
} }
} }
.icon {
height: 44px;
width: 44px;
}
&__label { &__label {
padding: 0 1em; padding: 0 1em;
flex-grow: 1; flex-grow: 1;

View File

@ -89,17 +89,21 @@ const ShareWith: React.FC<Props> = ({ room, permission, shares: allShares, setSh
{(share.permission === Permission.Admin) && ` (${t('bbb', 'admin')})`}</h5> {(share.permission === Permission.Admin) && ` (${t('bbb', 'admin')})`}</h5>
</div> </div>
{(share.id > -1 && permission === Permission.Moderator && isOwner) && <div className="bbb-shareWith__item__action"> {(share.id > -1 && permission === Permission.Moderator && isOwner) && <div className="bbb-shareWith__item__action">
<a className={`icon icon-shared icon-visible ${share.permission === Permission.Admin ? 'bbb-icon-selected' : 'bbb-icon-unselected'}`} <button className="action-item"
onClick={ev => { onClick={ev => {
ev.preventDefault(); ev.preventDefault();
toggleAdminShare(share); toggleAdminShare(share);
}} }}
title={t('bbb', 'Share')} /> title={t('bbb', 'Share')}>
<span className={`icon icon-shared icon-visible ${share.permission === Permission.Admin ? 'bbb-icon-selected' : 'bbb-icon-unselected'}`}></span>
</button>
</div>} </div>}
{(share.id > -1 && isOwner) && <div className="bbb-shareWith__item__action"> {(share.id > -1 && isOwner) && <div className="bbb-shareWith__item__action">
<a className="icon icon-delete icon-visible" <button className="action-item"
onClick={ev => {ev.preventDefault(); deleteRoomShare(share.id);}} onClick={ev => {ev.preventDefault(); deleteRoomShare(share.id);}}
title={t('bbb', 'Delete')} /> title={t('bbb', 'Delete')}>
<span className="icon icon-delete icon-visible"></span>
</button>
</div>} </div>}
</li> </li>
); );