Navigator: quieter room icons, Join as a text action, calmer unread badge #95

Merged
void merged 1 commit from void/nav-quiet into dev 2026-11-11 16:56:50 +00:00
5 changed files with 33 additions and 26 deletions

View file

@ -32,8 +32,10 @@ export const NavLevel = style({
paddingLeft: LEVEL_STEP,
});
// Chevrons and room icons share one resting weight, so a foldout is not outweighed by its rooms.
// Chevrons and room icons are matched in weight, so a foldout is not outweighed by its rooms.
export const NAV_ICON_REST_OPACITY = 0.6;
// A room's glyph is bigger and denser than the chevron, so it rests lighter to read as the same weight.
export const NAV_ROOM_ICON_REST_OPACITY = 0.42;
export const NAV_ICON_UNREAD_OPACITY = 0.9;
export const NavCategory = style([
@ -264,22 +266,18 @@ globalStyle(`:root[data-scene] ${NavItemBase} svg, :root[data-scene] ${NavItemBa
},
});
// The Join action on a phone is a plain underlined word, not a pill.
// The Join action is a plain underlined word on every screen, not a pill.
export const NavAction = style({
'@media': {
[PHONE]: {
selectors: {
'&&': {
backgroundColor: 'transparent',
boxShadow: 'none',
border: 'none',
borderRadius: 0,
minWidth: 0,
textDecoration: 'underline',
textUnderlineOffset: toRem(4),
flexShrink: 0,
},
},
selectors: {
'&&': {
backgroundColor: 'transparent',
boxShadow: 'none',
border: 'none',
borderRadius: 0,
minWidth: 0,
textDecoration: 'underline',
textUnderlineOffset: toRem(4),
flexShrink: 0,
},
},
});

View file

@ -22,7 +22,8 @@ export function UnreadBadge({ highlight, count }: UnreadBadgeProps) {
<Badge
variant={highlight ? 'Success' : 'Secondary'}
size={count > 0 ? '400' : '200'}
fill="Solid"
// A mention is the one solid pill; plain unread is a soft tint, so a row's count is never its loudest part.
fill={highlight ? 'Solid' : 'Soft'}
radii="Pill"
outlined={false}
>

View file

@ -1,7 +1,7 @@
import React from 'react';
import { Box, Icon, Icons, Text } from 'folds';
import { NavGutter, NavItem, NavItemContent, NavLink } from '../../components/nav';
import { NAV_ICON_REST_OPACITY, NavLabel } from '../../components/nav/styles.css';
import { NAV_ROOM_ICON_REST_OPACITY, NavLabel } from '../../components/nav/styles.css';
import { getDeskPath } from '../../pages/pathUtils';
import { deskFor } from './source';
@ -14,7 +14,11 @@ export function DeskEntry({ mind }: { mind: string }) {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<NavGutter>
<Icon src={Icons.Bookmark} size="100" style={{ opacity: NAV_ICON_REST_OPACITY }} />
<Icon
src={Icons.Bookmark}
size="100"
style={{ opacity: NAV_ROOM_ICON_REST_OPACITY }}
/>
</NavGutter>
<Text className={NavLabel} as="span" size="Inherit" truncate>
{open > 0 ? `Desk · ${open} open` : 'Desk'}

View file

@ -12,7 +12,7 @@ import {
NavItemContent,
NavLevel,
} from '../../components/nav';
import { NAV_ICON_REST_OPACITY, NavAction, NavLabel } from '../../components/nav/styles.css';
import { NAV_ROOM_ICON_REST_OPACITY, NavAction, NavLabel } from '../../components/nav/styles.css';
import { UseStateProvider } from '../../components/UseStateProvider';
import { JoinAddressPrompt } from '../../components/join-address-prompt';
import { RoomNavCategoryButton, RoomNavItem } from '../room-nav';
@ -86,7 +86,7 @@ function JoinRow({ room }: { room: EstateRoom }) {
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<NavGutter>
<Avatar size="200" radii="400">
<Icon src={Icons.Hash} size="100" style={{ opacity: NAV_ICON_REST_OPACITY }} />
<Icon src={Icons.Hash} size="100" style={{ opacity: NAV_ROOM_ICON_REST_OPACITY }} />
</Avatar>
</NavGutter>
<Text className={NavLabel} as="span" size="Inherit" truncate>
@ -108,7 +108,7 @@ function JoinRow({ room }: { room: EstateRoom }) {
variant={room.state === 'invited' ? 'Primary' : 'Secondary'}
fill="Soft"
radii="Pill"
before={busy ? <Spinner size="100" /> : <Icon src={Icons.Plus} size="50" />}
before={busy ? <Spinner size="100" /> : undefined}
onClick={join}
disabled={busy}
aria-label={`Join ${room.name}`}
@ -269,7 +269,11 @@ function EntryPoints() {
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<NavGutter>
<Avatar size="200" radii="400">
<Icon src={Icons.Plus} size="100" style={{ opacity: NAV_ICON_REST_OPACITY }} />
<Icon
src={Icons.Plus}
size="100"
style={{ opacity: NAV_ROOM_ICON_REST_OPACITY }}
/>
</Avatar>
</NavGutter>
<Text as="span" size="Inherit" truncate>
@ -291,7 +295,7 @@ function EntryPoints() {
<Icon
src={Icons.Link}
size="100"
style={{ opacity: NAV_ICON_REST_OPACITY }}
style={{ opacity: NAV_ROOM_ICON_REST_OPACITY }}
/>
</Avatar>
</NavGutter>

View file

@ -22,7 +22,7 @@ import FocusTrap from 'focus-trap-react';
import { useAtom, useAtomValue } from 'jotai';
import { NavGutter, NavItem, NavItemContent, NavItemOptions, NavLink } from '../../components/nav';
import {
NAV_ICON_REST_OPACITY,
NAV_ROOM_ICON_REST_OPACITY,
NAV_ICON_UNREAD_OPACITY,
NavLabel,
} from '../../components/nav/styles.css';
@ -354,7 +354,7 @@ export function RoomNavItem({
) : (
<RoomIcon
style={{
opacity: unread ? NAV_ICON_UNREAD_OPACITY : NAV_ICON_REST_OPACITY,
opacity: unread ? NAV_ICON_UNREAD_OPACITY : NAV_ROOM_ICON_REST_OPACITY,
}}
filled={selected}
size="100"