style(settings): flatten the permissions page into Dawn sections and swap the peek checkmarks for icons

This commit is contained in:
heaven 2026-06-04 12:26:30 +03:00
parent fa17029a45
commit e06ab508f9
2 changed files with 105 additions and 135 deletions

View file

@ -4,9 +4,8 @@ import { Badge, Box, Button, Chip, config, Icon, Icons, Menu, Spinner, Text } fr
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import produce from 'immer'; import produce from 'immer';
import type { StateEvents } from 'matrix-js-sdk'; import type { StateEvents } from 'matrix-js-sdk';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
import { SettingTile } from '../../../components/setting-tile'; import { SettingTile } from '../../../components/setting-tile';
import { SettingsSection } from '../../settings/SettingsSection';
import { import {
applyPermissionPower, applyPermissionPower,
getPermissionPower, getPermissionPower,
@ -120,53 +119,43 @@ export function PermissionGroups({
const powerChanges = value !== power; const powerChanges = value !== power;
return ( return (
<Box direction="Column" gap="100"> <SettingsSection label={t('RoomSettings.users')}>
<Text size="L400">{t('RoomSettings.users')}</Text> <SettingTile
<SequenceCard title={t('RoomSettings.default_power')}
variant="SurfaceVariant" description={t('RoomSettings.default_power_desc')}
className={SequenceCardStyle} after={
direction="Column" <PowerSwitcher
gap="400" powerLevelTags={powerLevelTags}
> value={value}
<SettingTile onChange={(v) => handleChangePermission(USER_DEFAULT_LOCATION, v, power)}
title={t('RoomSettings.default_power')} >
description={t('RoomSettings.default_power_desc')} {(handleOpen, opened) => (
after={ <Chip
<PowerSwitcher variant={powerChanges ? 'Success' : 'Secondary'}
powerLevelTags={powerLevelTags} outlined={powerChanges}
value={value} fill="Soft"
onChange={(v) => handleChangePermission(USER_DEFAULT_LOCATION, v, power)} radii="Pill"
> aria-selected={opened}
{(handleOpen, opened) => ( disabled={!canEdit || applyingChanges}
<Chip after={
variant={powerChanges ? 'Success' : 'Secondary'} powerChanges && <Badge size="200" variant="Success" fill="Solid" radii="Pill" />
outlined={powerChanges} }
fill="Soft" before={
radii="Pill" canEdit && (
aria-selected={opened} <Icon size="50" src={opened ? Icons.ChevronTop : Icons.ChevronBottom} />
disabled={!canEdit || applyingChanges} )
after={ }
powerChanges && ( onClick={handleOpen}
<Badge size="200" variant="Success" fill="Solid" radii="Pill" /> >
) <Text size="B300" truncate>
} {tag.name}
before={ </Text>
canEdit && ( </Chip>
<Icon size="50" src={opened ? Icons.ChevronTop : Icons.ChevronBottom} /> )}
) </PowerSwitcher>
} }
onClick={handleOpen} />
> </SettingsSection>
<Text size="B300" truncate>
{tag.name}
</Text>
</Chip>
)}
</PowerSwitcher>
}
/>
</SequenceCard>
</Box>
); );
}; };
@ -174,8 +163,7 @@ export function PermissionGroups({
<> <>
{renderUserGroup()} {renderUserGroup()}
{permissionGroups.map((group, groupIndex) => ( {permissionGroups.map((group, groupIndex) => (
<Box key={groupIndex} direction="Column" gap="100"> <SettingsSection key={groupIndex} label={group.name}>
<Text size="L400">{group.name}</Text>
{group.items.map((item, itemIndex) => { {group.items.map((item, itemIndex) => {
const power = getPermissionPower(powerLevels, item.location); const power = getPermissionPower(powerLevels, item.location);
const powerUpdate = permissionUpdate.get(item.location); const powerUpdate = permissionUpdate.get(item.location);
@ -185,60 +173,48 @@ export function PermissionGroups({
const powerChanges = value !== power; const powerChanges = value !== power;
return ( return (
<SequenceCard <SettingTile
key={itemIndex} key={itemIndex}
variant="SurfaceVariant" title={item.name}
className={SequenceCardStyle} description={item.description}
direction="Column" after={
gap="400" <PowerSwitcher
> powerLevelTags={powerLevelTags}
<SettingTile value={value}
title={item.name} onChange={(v) => handleChangePermission(item.location, v, power)}
description={item.description} >
after={ {(handleOpen, opened) => (
<PowerSwitcher <Chip
powerLevelTags={powerLevelTags} variant={powerChanges ? 'Success' : 'Secondary'}
value={value} outlined={powerChanges}
onChange={(v) => handleChangePermission(item.location, v, power)} fill="Soft"
> radii="Pill"
{(handleOpen, opened) => ( aria-selected={opened}
<Chip disabled={!canEdit || applyingChanges}
variant={powerChanges ? 'Success' : 'Secondary'} after={
outlined={powerChanges} powerChanges && (
fill="Soft" <Badge size="200" variant="Success" fill="Solid" radii="Pill" />
radii="Pill" )
aria-selected={opened} }
disabled={!canEdit || applyingChanges} before={
after={ canEdit && (
powerChanges && ( <Icon size="50" src={opened ? Icons.ChevronTop : Icons.ChevronBottom} />
<Badge size="200" variant="Success" fill="Solid" radii="Pill" /> )
) }
} onClick={handleOpen}
before={ >
canEdit && ( <Text size="B300" truncate>
<Icon {tag.name}
size="50" </Text>
src={opened ? Icons.ChevronTop : Icons.ChevronBottom} {value < maxPower && <Text size="T200">{t('RoomSettings.and_above')}</Text>}
/> </Chip>
) )}
} </PowerSwitcher>
onClick={handleOpen} }
> />
<Text size="B300" truncate>
{tag.name}
</Text>
{value < maxPower && (
<Text size="T200">{t('RoomSettings.and_above')}</Text>
)}
</Chip>
)}
</PowerSwitcher>
}
/>
</SequenceCard>
); );
})} })}
</Box> </SettingsSection>
))} ))}
{hasChanges && ( {hasChanges && (

View file

@ -14,11 +14,12 @@ import {
toRem, toRem,
config, config,
color, color,
Icon,
Icons,
} from 'folds'; } from 'folds';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
import { getPowers, usePowerLevelTags } from '../../../hooks/usePowerLevelTags'; import { getPowers, usePowerLevelTags } from '../../../hooks/usePowerLevelTags';
import { SettingTile } from '../../../components/setting-tile'; import { SettingTile } from '../../../components/setting-tile';
import { SettingsSection } from '../../settings/SettingsSection';
import { getPermissionPower, IPowerLevels } from '../../../hooks/usePowerLevels'; import { getPermissionPower, IPowerLevels } from '../../../hooks/usePowerLevels';
import { useRoom } from '../../../hooks/useRoom'; import { useRoom } from '../../../hooks/useRoom';
import { PowerColorBadge, PowerIcon } from '../../../components/power'; import { PowerColorBadge, PowerIcon } from '../../../components/power';
@ -77,15 +78,20 @@ function PeekPermissions({ powerLevels, power, permissionGroups, children }: Pee
const hasPower = requiredPower <= power; const hasPower = requiredPower <= power;
return ( return (
<Text <Box key={itemIndex} alignItems="Center" gap="200">
key={itemIndex} <Icon
size="T200" size="50"
style={{ src={hasPower ? Icons.Check : Icons.Cross}
color: hasPower ? undefined : color.Critical.Main, style={{
}} color: hasPower ? color.Success.Main : color.Surface.OnContainer,
> opacity: hasPower ? 1 : 0.4,
{hasPower ? '✅' : '❌'} {item.name} flexShrink: 0,
</Text> }}
/>
<Text size="T200" style={{ opacity: hasPower ? 1 : 0.6 }}>
{item.name}
</Text>
</Box>
); );
})} })}
</div> </div>
@ -120,19 +126,12 @@ export function Powers({ powerLevels, permissionGroups, onEdit }: PowersProps) {
creatorsTag.icon && getPowerTagIconSrc(mx, useAuthentication, creatorsTag.icon); creatorsTag.icon && getPowerTagIconSrc(mx, useAuthentication, creatorsTag.icon);
return ( return (
<Box direction="Column" gap="100"> <Box direction="Column" gap="700">
{creators.size > 0 && ( {creators.size > 0 && (
<SequenceCard <SettingsSection
variant="SurfaceVariant" label={t('RoomSettings.founders')}
className={SequenceCardStyle} footnote={t('RoomSettings.founders_desc')}
direction="Column"
gap="400"
> >
<SettingTile
title={t('RoomSettings.founders')}
description={t('RoomSettings.founders_desc')}
/>
<SettingTile> <SettingTile>
<Box gap="200" wrap="Wrap"> <Box gap="200" wrap="Wrap">
<Chip <Chip
@ -148,17 +147,13 @@ export function Powers({ powerLevels, permissionGroups, onEdit }: PowersProps) {
</Chip> </Chip>
</Box> </Box>
</SettingTile> </SettingTile>
</SequenceCard> </SettingsSection>
)} )}
<SequenceCard <SettingsSection
variant="SurfaceVariant" label={t('RoomSettings.power_levels')}
className={SequenceCardStyle} footnote={t('RoomSettings.power_levels_desc')}
direction="Column"
gap="400"
> >
<SettingTile <SettingTile
title={t('RoomSettings.power_levels')}
description={t('RoomSettings.power_levels_desc')}
after={ after={
onEdit && ( onEdit && (
<Box gap="200"> <Box gap="200">
@ -175,8 +170,7 @@ export function Powers({ powerLevels, permissionGroups, onEdit }: PowersProps) {
</Box> </Box>
) )
} }
/> >
<SettingTile>
<Box gap="200" wrap="Wrap"> <Box gap="200" wrap="Wrap">
{getPowers(powerLevelTags).map((power) => { {getPowers(powerLevelTags).map((power) => {
const tag = powerLevelTags[power]; const tag = powerLevelTags[power];
@ -208,7 +202,7 @@ export function Powers({ powerLevels, permissionGroups, onEdit }: PowersProps) {
})} })}
</Box> </Box>
</SettingTile> </SettingTile>
</SequenceCard> </SettingsSection>
</Box> </Box>
); );
} }