Skip to content

Add donate and settings order #1447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 5, 2025
42 changes: 12 additions & 30 deletions ts/components/icon/Icons.tsx

Large diffs are not rendered by default.

18 changes: 15 additions & 3 deletions ts/components/icon/LucideIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SessionDataTestId } from 'react';
import type { CSSProperties, SessionDataTestId } from 'react';
import styled from 'styled-components';

const LucideIconWrapper = styled.div<{ iconColor?: string; iconSize: string }>`
Expand All @@ -12,14 +12,26 @@ export type LucideIconProps = {
iconColor?: string;
iconSize: string;
dataTestId?: SessionDataTestId;
style?: CSSProperties;
};

/**
* This is a wrapper around Lucide icons with unicode.
*/
export const LucideIcon = ({ unicode, iconColor, iconSize, dataTestId }: LucideIconProps) => {
export const LucideIcon = ({
unicode,
iconColor,
iconSize,
dataTestId,
style,
}: LucideIconProps) => {
return (
<LucideIconWrapper iconColor={iconColor} iconSize={iconSize} data-testid={dataTestId}>
<LucideIconWrapper
iconColor={iconColor}
iconSize={iconSize}
data-testid={dataTestId}
style={style}
>
{unicode}
</LucideIconWrapper>
);
Expand Down
155 changes: 83 additions & 72 deletions ts/components/icon/SessionIconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ const StyledSessionIconButton = styled.button<{ color?: string; $isSelected?: bo
};`}
}

color: ${props =>
props.color || props.$isSelected
? 'var(--button-icon-stroke-selected-color)'
: 'var(--button-icon-stroke-color)'};

${props => props.disabled && 'cursor: not-allowed;'}

&:hover svg path {
Expand Down Expand Up @@ -130,77 +135,83 @@ const SessionIconButtonInner = forwardRef<HTMLButtonElement, SessionIconButtonPr

export const SessionIconButton = memo(SessionIconButtonInner, _.isEqual);

export const SessionLucideIconButton = (
props: Pick<
SessionIconButtonProps,
| 'onClick'
| 'disabled'
| 'isSelected'
| 'margin'
| 'padding'
| 'ariaLabel'
| 'title'
| 'dataTestId'
| 'dataTestIdIcon'
| 'style'
| 'tabIndex'
> &
Pick<LucideIconProps, 'unicode' | 'iconSize' | 'iconColor'>
) => {
const {
unicode,
iconSize,
isSelected: $isSelected,
margin,
padding,
ariaLabel,
title,
dataTestId,
dataTestIdIcon,
style,
iconColor,
tabIndex,
disabled,
onClick,
} = props;
export type SessionLucideIconButtonProps = Pick<
SessionIconButtonProps,
| 'onClick'
| 'disabled'
| 'isSelected'
| 'margin'
| 'padding'
| 'ariaLabel'
| 'title'
| 'dataTestId'
| 'dataTestIdIcon'
| 'style'
| 'tabIndex'
| 'children'
> &
Pick<LucideIconProps, 'unicode' | 'iconSize' | 'iconColor'>;

const clickHandler = (e: MouseEvent<HTMLButtonElement>) => {
if (!disabled && onClick) {
e.stopPropagation();
onClick(e);
}
};
const keyPressHandler = (e: KeyboardEvent<HTMLButtonElement>) => {
if (e.currentTarget.tabIndex > -1 && e.key === 'Enter' && !disabled && onClick) {
e.stopPropagation();
onClick();
}
};
export const SessionLucideIconButton = forwardRef<HTMLButtonElement, SessionLucideIconButtonProps>(
(props, ref) => {
const {
unicode,
iconSize,
isSelected: $isSelected,
margin,
padding,
ariaLabel,
title,
dataTestId,
dataTestIdIcon,
style,
iconColor,
tabIndex,
disabled,
onClick,
children,
} = props;

return (
<StyledSessionIconButton
color={iconColor}
$isSelected={$isSelected}
title={title}
aria-label={ariaLabel}
onClick={clickHandler}
style={{
...style,
display: style?.display ? style.display : 'flex',
margin: margin || '',
padding: padding || '',
}}
tabIndex={tabIndex}
onKeyDown={keyPressHandler}
disabled={disabled}
data-testid={dataTestId}
>
<LucideIcon
unicode={unicode}
iconSize={iconSize}
iconColor={iconColor}
dataTestId={dataTestIdIcon}
/>
</StyledSessionIconButton>
);
};
const clickHandler = (e: MouseEvent<HTMLButtonElement>) => {
if (!disabled && onClick) {
e.stopPropagation();
onClick(e);
}
};
const keyPressHandler = (e: KeyboardEvent<HTMLButtonElement>) => {
if (e.currentTarget.tabIndex > -1 && e.key === 'Enter' && !disabled && onClick) {
e.stopPropagation();
onClick();
}
};

return (
<StyledSessionIconButton
color={iconColor}
$isSelected={$isSelected}
title={title}
aria-label={ariaLabel}
onClick={clickHandler}
style={{
...style,
display: style?.display ? style.display : 'flex',
margin: margin || '',
padding: padding || '',
}}
tabIndex={tabIndex}
onKeyDown={keyPressHandler}
disabled={disabled}
data-testid={dataTestId}
ref={ref}
>
<LucideIcon
unicode={unicode}
iconSize={iconSize}
iconColor={iconColor}
dataTestId={dataTestIdIcon}
/>
{children}
</StyledSessionIconButton>
);
}
);
2 changes: 1 addition & 1 deletion ts/components/icon/SessionNotificationCount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const StyledCountContainer = styled.div<{ $centeredOnTop: boolean }>`
padding: ${props => (props.$centeredOnTop ? '1px 3px 0' : '1px 4px')};

position: absolute;
top: ${props => (props.$centeredOnTop ? '-10px' : '27px')};
top: ${props => (props.$centeredOnTop ? '-10px' : '22px')};
left: ${props => (props.$centeredOnTop ? '50%' : '28px')};

font-size: var(--font-size-xs);
Expand Down
11 changes: 11 additions & 0 deletions ts/components/icon/lucide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ export enum LUCIDE_ICONS_UNICODE {
USER_ROUND_X = '',
USER_ROUND_CHECK = '',
PENCIL = '',
HEART = '',
LOCK_KEYHOLE = '',
MESSAGE_SQUARE = '',
MESSAGE_SQUARE_WARNING = '',
PAINTBRUSH_VERTICAL = '',
CIRCLE_CHECK = '',
MOON = '',
SUN_MEDIUM = '',
SETTINGS = '',
SQUARE_CODE = '',
CHEVRON_RIGHT = '',
}

/**
Expand Down
52 changes: 29 additions & 23 deletions ts/components/leftpane/ActionsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ import { getSwarmPollingInstance } from '../../session/apis/snode_api';
import { UserUtils } from '../../session/utils';
import { Avatar, AvatarSize } from '../avatar/Avatar';
import { ActionPanelOnionStatusLight } from '../dialog/OnionStatusPathDialog';
import { SessionIconButton } from '../icon/SessionIconButton';
import {
SessionLucideIconButton,
type SessionLucideIconButtonProps,
} from '../icon/SessionIconButton';
import { LeftPaneSectionContainer } from './LeftPaneSectionContainer';

import { SettingsKey } from '../../data/settings-key';
Expand All @@ -61,6 +64,7 @@ import { useCheckReleasedFeatures } from '../../hooks/useCheckReleasedFeatures';
import { useDebugMode } from '../../state/selectors/debug';
import { networkDataActions } from '../../state/ducks/networkData';
import { isSesh101ReadyOutsideRedux } from '../../state/selectors/releasedFeatures';
import { LUCIDE_ICONS_UNICODE } from '../icon/lucide';

const Section = (props: { type: SectionType }) => {
const ourNumber = useSelector(getOurNumber);
Expand All @@ -71,7 +75,7 @@ const Section = (props: { type: SectionType }) => {
const isModalVisible = useSelector(getIsModalVisible);
const isDarkTheme = useIsDarkTheme();
const focusedSection = useSelector(getFocusedSection);
const isSelected = focusedSection === props.type;
const isSelected = focusedSection === type;

const handleClick = () => {
if (type === SectionType.Profile) {
Expand Down Expand Up @@ -125,38 +129,42 @@ const Section = (props: { type: SectionType }) => {

const unreadToShow = type === SectionType.Message ? globalUnreadMessageCount : undefined;

const buttonProps = {
iconSize: '22px',
padding: 'var(--margins-lg)',
onClick: handleClick,
isSelected,
} satisfies Omit<SessionLucideIconButtonProps, 'unicode' | 'dataTestId'>;

switch (type) {
case SectionType.Message:
return (
<SessionIconButton
iconSize="medium"
<SessionLucideIconButton
{...buttonProps}
dataTestId="message-section"
iconType={'chatBubble'}
onClick={handleClick}
isSelected={isSelected}
unicode={LUCIDE_ICONS_UNICODE.MESSAGE_SQUARE}
style={{
position: 'relative',
}}
>
{Boolean(unreadToShow) && <SessionNotificationCount count={unreadToShow} />}
</SessionIconButton>
</SessionLucideIconButton>
);
case SectionType.Settings:
return (
<SessionIconButton
iconSize="medium"
<SessionLucideIconButton
{...buttonProps}
dataTestId="settings-section"
iconType={'gear'}
onClick={handleClick}
isSelected={isSelected}
unicode={LUCIDE_ICONS_UNICODE.SETTINGS}
ref={settingsIconRef}
/>
);
case SectionType.DebugMenu:
return (
<SessionIconButton
iconSize="medium"
<SessionLucideIconButton
{...buttonProps}
unicode={LUCIDE_ICONS_UNICODE.SQUARE_CODE}
dataTestId="debug-menu-section"
iconType={'debug'}
onClick={handleClick}
isSelected={isSelected}
/>
);
case SectionType.PathIndicator:
Expand All @@ -170,12 +178,10 @@ const Section = (props: { type: SectionType }) => {
case SectionType.ColorMode:
default:
return (
<SessionIconButton
iconSize="medium"
iconType={isDarkTheme ? 'moon' : 'sun'}
<SessionLucideIconButton
{...buttonProps}
unicode={isDarkTheme ? LUCIDE_ICONS_UNICODE.MOON : LUCIDE_ICONS_UNICODE.SUN_MEDIUM}
dataTestId="theme-section"
onClick={handleClick}
isSelected={isSelected}
/>
);
}
Expand Down
Loading
Loading