Skip to content
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

feat: Conversation requests screen UI components #1608

Merged
merged 6 commits into from
Feb 18, 2025
Merged

Conversation

lourou
Copy link
Member

@lourou lourou commented Feb 18, 2025

Replace Segmented Controller with new toggle design

  • Removed old segmented controller component
  • Implemented new toggle design using Chip components as per Figma design

Add delete all button to header

  • Added a delete all button with bin icon to the screen header
  • Implemented confirmation dialog before deletion
  • Used existing HeaderAction component and icon system
  • Added placeholder for delete functionality

Linked to #1589

Screen recording

@lourou lourou requested a review from a team as a code owner February 18, 2025 13:35
Copy link
Collaborator

@thierryskoda thierryskoda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Can we refactor the Chip component to not have name or avatarUri and showAvatar? And make it more composable?

Here's some code I generated with AI. Maybe need to verify but something like this would be amazing.

import { Avatar as RNAvatar } from "@/components/Avatar";
import { Center } from "@/design-system/Center";
import { Text as RNText } from "@/design-system/Text";
import { useAppTheme } from "@/theme/useAppTheme";
import React from "react";
import { Pressable, StyleProp, ViewStyle, TextStyle } from "react-native";

const ChipContext = React.createContext<{
  size: "sm" | "md";
  disabled?: boolean;
  isSelected?: boolean;
} | null>(null);

function useChipContext() {
  const context = React.useContext(ChipContext);
  if (!context) {
    throw new Error("Chip components must be used within a Chip");
  }
  return context;
}

type ChipProps = {
  isSelected?: boolean;
  onPress?: () => void;
  size?: "sm" | "md";
  disabled?: boolean;
  variant?: "filled" | "outlined";
  children: React.ReactNode;
};

export function Chip({
  children,
  isSelected,
  onPress,
  size = "sm",
  disabled,
  variant = "outlined",
}: ChipProps) {
  const styles = useChipStyles({ variant });

  return (
    <ChipContext.Provider value={{ size, disabled, isSelected }}>
      <Pressable
        onPress={onPress}
        disabled={disabled}
        style={({ pressed }) => [
          styles.$container,
          isSelected && styles.$selectedContainer,
          disabled && styles.$disabledContainer,
          pressed && styles.$pressedContainer,
        ]}
      >
        <Center style={styles.$content}>{children}</Center>
      </Pressable>
    </ChipContext.Provider>
  );
}

type ChipTextProps = {
  children: string;
  style?: StyleProp<TextStyle>;
};

export function ChipText({ children, style }: ChipTextProps) {
  const { size, disabled, isSelected } = useChipContext();
  const styles = useChipStyles({ variant: "outlined" });

  return (
    <RNText
      preset={size === "sm" ? "small" : "body"}
      style={[
        style,
        disabled && styles.$disabledText,
        isSelected && styles.$selectedText,
      ]}
    >
      {children}
    </RNText>
  );
}

type ChipIconProps = {
  children: React.ReactNode;
};

export function ChipIcon({ children }: ChipIconProps) {
  return children;
}

type ChipAvatarProps = {
  uri?: string;
  name: string;
};

export function ChipAvatar({ uri, name }: ChipAvatarProps) {
  const { theme } = useAppTheme();
  return <RNAvatar uri={uri} name={name} size={theme.avatarSize.xs} />;
}

// Usage:
{
  /* 
<Chip size="sm">
  <ChipAvatar uri={avatarUri} name={name} />
  <ChipText>{name}</ChipText>
</Chip>
*/
}

export function useChipStyles({ variant }: { variant: "filled" | "outlined" }) {
  const { theme } = useAppTheme();

  const $container = {
    borderRadius: theme.spacing.xs,
    borderWidth: variant === "outlined" ? theme.borderWidth.sm : 0,
    borderColor: theme.colors.border.subtle,
    backgroundColor:
      variant === "outlined"
        ? theme.colors.background.surface
        : theme.colors.fill.minimal,
    paddingVertical:
      theme.spacing.xxs -
      (variant === "outlined" ? theme.borderWidth.sm * 2 : 0),
    paddingHorizontal: theme.spacing.xs,
  } satisfies StyleProp<ViewStyle>;

  const $content = {
    columnGap: theme.spacing.xxxs,
    height: theme.spacing.md,
  } satisfies StyleProp<ViewStyle>;

  return {
    constants: {
      chipHeight: $container.paddingVertical * 2 + $content.height,
    },
    $container,
    $selectedContainer: {
      backgroundColor: theme.colors.fill.minimal,
      borderColor:
        variant === "outlined" ? theme.colors.fill.minimal : "transparent",
    },
    $content,
    $disabledContainer: {
      opacity: 0.5,
    },
    $pressedContainer: {
      opacity: 0.8,
    },
    $disabledText: {
      color: theme.colors.text.muted,
    },
    $selectedText: {
      color: theme.colors.text.accent,
    },
  } as const;
}

const { theme } = useAppTheme();

return (
<View
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use HStack and no need flexDireciton: row

@lourou
Copy link
Member Author

lourou commented Feb 18, 2025

Yes @thierryskoda great idea for <Chip> component, I'll make it composable and update existing instances!

@lourou lourou requested a review from thierryskoda February 18, 2025 16:26
import { Center } from "@/design-system/Center";
import { Text } from "@/design-system/Text";
import { Text as RNText } from "@/design-system/Text";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why Text as RNText ? Why not just Text? same with RNAvatar

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed! That should not have been there :)

name: string;
avatarUri?: string;
const ChipContext = React.createContext<{
size: "sm" | "md";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should have type IChipSize = 'sm' | 'md'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

@lourou lourou requested a review from thierryskoda February 18, 2025 16:51
@lourou lourou merged commit fcbc0e6 into main Feb 18, 2025
2 of 4 checks passed
@lourou lourou deleted the lr/consent-ui-requests branch February 18, 2025 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants