Sefar by Yassir

Welcome to Sefar by Yassir!

Migrate from Sefar 1.1.0 to 1.2.0 #

Breaking Changes #

VerticalCard #

VerticalCard signature has been updated to better match the design logic.

val image = Image(
    resId = R.drawable.ic_avatar,
    isEnable = isImageEnable,  //optional
)

val defaultType = VerticalCardType.Default(
    price = "100$", //optional
    incrementButton = SecondaryAction.IncrementButton(), //optional
)

VerticalCard(
-   element = VerticalCardElement(..)
+   image = image,
+   title = "Card title",
+   type = defaultType,
    size = VerticalCardSize.Large,
)

Migrate from Sefar 1.0.0 to 1.1.0 #

Breaking Changes #

RatingBar #

Add a rating parameter that can be used to give an initial value to the RatingBar.
It has a default value of 0f and can break your code only if you are not using named arguments for all the parameters.

var rating by remember { mutableFloatStateOf(0f) }

RatingBar(
    modifier = Modifier.padding(16.dp), //optional
    allowDoubleTap = false, //optional
++  rating = rating, //optional
    onRatingChange = { newRating -> rating = newRating }
)

Backdrop #

We have a possible breaking change in the Backdrop of CustomState type. An IncrementButton can now optionally be added to this type of backdrop. This might break your code if you are using the trailing lamda syntax for the customContent argument:

Backdrop(
    modiefier = Modifier.padding(YassirTheme.spacing.spacing0_5), // optional
    backDropType =  BackdropType.CustomState(
        isElevatedFooter = false,
        requiredHeight = 600.dp,
        customContent = { 
            // create custom component
            
        },
+       incrementButton = BackdropIncrementButton(
+           maxValue = 5,
+           onValueChanged = {newValue -> }
+       ),
    ),
    backdropHeaderItem = BackdropHeaderItem(
      title = "Title",
      subtitle = "Subtitle",
      tabsList = tabsList,
      onBackClick = {},
    ), // optional
    primaryAction = Action(
        text = "Primary Action",
        startIconResId = null, //optional
        endIconResId = null, //optional
        onClick = {}
    ), // optional
    secondaryAction = Action(
        text = "Secondary Action",
        startIconResId = null, //optional
        endIconResId = null, //optional
        onClick = {}
    ), // optional
    tertiaryAction = Action(
        text = "Teritary Action",
        startIconResId = null, //optional
        endIconResId = null, //optional
        onClick = {}
    ), // optional
    isVisible = true, // optional
    screenState = ScreenState.FullScreen, // optional
    windowInsets = WindowInsets(0, 0, 0, 0), // optional
    containerColor = YassirTheme.colors.surfaceNeutralHigh, // optional
    sheetState = SheetState(
        skipPartiallyExpanded = true,
        density = LocalDensity.current,
        initialValue = SheetValue.Expanded
    ), // optional
    onDismissRequest = {  }
)

Migrate from Sefar 0.14.1 to 1.0.0 #

Deprecations #

The following APIs/parameters have been deprecated and replaced by new alternative:

GenericInput #

The old signature of the GenericInput contained a long list of params, some of this params has been grouped under InputFieldStyleParams and InputFieldStateParams classes.

 fun GenericInput(
     modifier: Modifier = Modifier,
     value: String,
     label: String = "",
     placeholder: String = "",
     hint: String = "",
-    enabled: Boolean = true,
-    hasError: Boolean = false,
-    forceLtr: Boolean = true,
-    cursorAtEnd: Boolean = false,
-    showIconOnError: Boolean = true,
-    showScrollBars: Boolean = false,
-    filled: Boolean = false,
-    shiftTrailingComponent: Boolean = false,
-    isInteractive: Boolean = true,
-    maxLines: Int = 1,
-    fixedHeight: Dp? = null,
-    minHeight: Dp? = null,
-    maxHeight: Dp? = null,
+    styleParams : InputFieldStyleParams = InputFieldStyleParams(),
+    stateParams : InputFieldStateParams = InputFieldStateParams(),
     innerFieldStaticLeadingText: String? = null,
     leading: @Composable RowScope.(String) -> Unit = GenericInputDefaults.EmptyWithString,
     trailing: @Composable RowScope.(String) -> Unit = GenericInputDefaults.EmptyWithString,
-    labelTextStyle: TextStyle = YassirTheme.typography.bodyLargeBold,
-    textAlign: TextAlign = TextAlign.Start,
     keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
     keyboardActions: KeyboardActions = KeyboardActions.Default,
     visualTransformation: VisualTransformation = VisualTransformation.None,
     onHintClick: (() -> Unit)? = null,
     onValueChange: (String) -> Unit,
 )

Breaking Changes #

AvatarGroup #

We completely removed Large Size of Avatar Group, we now only support Extra Small, Small, and Medium. We also changed the proprty type from AvatarSize to AvatarGroupSize.

The following breaking changes require you to update your existing usage accordingly:

val listOfAvatars = listOf(
    AvatarGroupItem(
        avatarType = AvatarType.Initials, //Icon, Image, Initials variants
        name = "John Doe", // optional (for Initials variant)
        imageUrl = null, // optional (for Image variant)
        iconRes = R.drawable.ic_avatar, // optional (for Icon variant)
        imageRes = R.drawable.ic_avatar, // optional (for Image variant)
        hasTwoInitials = false // optional (for Initials variant)
    )
)
AvatarGroup (
    modifier = Modifier,
    avatars= listOfAvatars,
-   size = AvatarSize.Large,
+   size = AvatarGroupSize.Medium,
)

Password Input Field #

Password Input Field has got a new parameter “label”

PasswordInput(
    modifier = Modifier, // optional
    value = "text",
+   label = "Password", // optional
    isNumerical = true,
    enabled = true, // optional
    hasError = false, // optional
    placeholder = "placeholder", // optional
    hint = "hint", // optional
    onValueChange = { text = it },
    onHintClick = { /* action */ }, // optional
    onImeAction = { },  // optional
)

Text Area Input Field #

Text Area Input Field has got a new parameter “label”

TextAreaInput(
    text = "text",
    onValueChange = { },
    enabled = true,
    hasError = false,
+   label = "Label", // optional
    showScrollBars = false, // optional
    placeholder = stringResource(R.string.placeholder_text), // optional
    hint = if (hasHint) stringResource(R.string.hint_text) // optional
)

TopBar Actions - Slot #

No String is being passed for Slot anymore

TopBarActionType.Slot(
-    slot = { testPrefix -> }
+    slot = { 
        //custom content
     },            
)

Migrate from Sefar 0.14.1 to 0.14.2 #

TopBar #

We have added the ability to override the content(icons and title) color of the TopBar.

PS: This will only break your code if you are using the trailing lamda syntax for the leadingIconClick property instead of the named argument.

TopBar(
    contentType = TopBarContentType.Title(
        title = "Title",
        subtitle = "Subtitle",
        ratingText = "4.5"
    ),
    actionType = TopBarActionType.Button(
        text = "Button",
        onClick = { /* action */ }
    ),
    showBackground = true, // optional
    leadingIconClick = { /* action */ }, // optional
+   contentColor = LabelColors.LabelNeutralDefault, // optional
  )

Migrate from Sefar 0.13.1 to 0.14.1 #

Deprecations #

The following APIs or parameters have been deprecated and replaced by new alternatives:

PhoneInput #

Most of the the PhoneInput params now are grouped under PhoneInputConfig and CountryPickerConfig classes.

PhoneInput(
    modifier = Modifier.padding(YassirTheme.spacing.spacing3), // optional
-   hint = "Phone Number can't be empty!", // optional
-   hasError = true, // optional
-   hasLabel = true, // optional
-   enabled = true, // optional
-   isCountrySelectionEnabled = true, // optional
-   isCountryCodeTextEnabled = true, // optional
-   hasBackdropHeaderItem = true, // optional
-   countriesList = SupportedCountries.entries, // optional
-   initialSelectedCountryRegionCode: String = SupportedCountry.Algeria.regionCode // optional
-   countriesBackDropList: CountryCodeListType = CountryCodeListType.SupportedCounties // optional
-   countryBackdropTitle: String = "", // optional
-   backdropHintText: Int? = R.string.country_backdrop_hint, // optional
-   searchBackdropPlaceholder: String? = null,
-   onCountrySelected = null // optional,
    phoneNumber = "", // optional
+   config = PhoneInputConfig(), // optional
+   countryPickerConfig = CountryPickerConfig(), // optional
    onHintClick = { /* action */ },
    onImeAction = { /* action */ } // optional,
    onPhoneNumberChange = {phoneNumber, isValidPhoneNumber -> }, // optional
)

Breaking Changes #

The following breaking changes require you to update your existing usage accordingly:

Cards #

1.ActivityCard

Now you can modify all the ListItem properties.

    val contentProperties =
        ListItemContentProperties(
            title = "Title",
            description = "Description", // optional
            leading = LeadingElementType.Icon(
                iconRes = DrawableR.ic_ds_coins_hand,
                tint = YassirTheme.colors.labelNeutralDefault,
            ), // optional
            trailing = TrailingElementType.CheckBox(
                selectionState = trailingCheckBoxState,onClick = {},
            ), // optional
            upperDescription = "upperDescription", // optional
            onClickLabel = "", // optional
            tagProperties = TagProperties(
                text = "test tag",
                tagStyle = TagStyle.Neutral,
                size = YassirTagSize.Medium,
            ),
        )

    val transactionProperties =
        ListItemTransactionProperties(
            formattedAmount = "$ 54.00", // optional
            transactionType = TransactionType.Incoming, // optional
            transactionStatus = TransactionStatus.Pending, // optional
            currencyHidden = true, // optional
            transactionDateTime = Date(), // optional
        )

    val visualConfig =
        ListItemVisualConfig(
            size = ListItemSize.Medium, // optional
            isSelected = true, // optional
            isEnabled = true, // optional
            showDivider = true, // optional
            showOutline = true, // optional
            styleOverrides = ListItemStyleOverrides(
                roundedCornersSize = SpacingKey.SPACING_0, // optional
                verticalPaddingKey = SpacingKey.SPACING_1, // optional
                horizontalPaddingKey = SpacingKey.SPACING_1, // optional
                descriptionTextColorKey = YassirColorSchemeKey.LabelNeutralDefault, // optional
                titleTextColorKey = YassirColorSchemeKey.LabelPrimary, // optional
                itemBackgroundColorKey = YassirColorSchemeKey.SurfaceNeutralDefault, // optional
            ) // optional
        )
SefarActivityCard(
      modifier = Modifier, //optional
-     listItem = ActivityCardListItem(
-         title = "Title",
-         iconRes = DrawableR.ic_user, //optional
-         transactionStatus = TransactionStatus.Pending, //optional
-         transactionDateTime = Date(), //optional
-         balance = "1000 DZD" //optional
-     ),
+     listItem = ActivityCardListItem(
+         contentProperties = contentProperties,
+         transactionProperties = transactionProperties
+         visualConfig = visualConfig
+     ),
+     locale: Locale = currentLocale(), //optional
      body = ActivityCardBody.Text("Some Text for Preview"),
      actions = ActivityCardActions.Buttons(
          firstAction = ActivityAction(
            label = "Action",
            onClick = {},
              isEnabled = true
              ),
      ) //optional
  )

2.ShopCard

In ShopCardDetails class the isDirectlyAdjacent flag has been removed from the SideElement objects, now if the side element is a YassirLogo it will be adjacent to the text(title), if it is an IconWithLabel it will be on the far right (left if RTL).

ShopCard(
  modifier = Modifier.withTestPrefix("shop_card_screen"),
  shopCardDetails = ShopCardDetails(
  text = "Title",
  sideElement = if (hasYassirSideElement) {
- SideElement.YassirLogo(isDirectlyAdjacent = false)
+ SideElement.YassirLogo
  } else {
    SideElement.IconWithLabel(
-     isDirectlyAdjacent = hasSnugSideElement,
      iconResId = DrawableR.ic_plus_circle,
      iconLabel = "1"
      )
      },
  imageUrl = null, // optional
  imageResId = DrawableR.flag_morocco_rect, // optional
  leadingElementType = LeadingElementType.ImageAvatar(resourceId = R.drawable.ic_avatar), // optional
  desc = "Body", // optional
  primaryTag = TagDetails(
    text = "New",
    startIconResId = R.drawable.ic_map_mark
            ), // optional
  secondaryTag = TagDetails(
    text = "Discount",
    startIconResId = R.drawable.ic_map_mark
            ), // optional
  disabledTag = TagDetails(
      text = "Coming Soon",
      startIconResId = R.drawable.ic_map_mark), // optional
  iconButton = IconButtonDetails(
            iconResId = MapsIcons.Bus,
            contentDescription = null,
            ) // optional
  )
  isEnabled = isEnabled,
)

Backdrop EmptyState #

For the EmptyState backdrops with line and dot carousels, we have removed the types(black type, and white type) keeping only the branded one, therefore there will be no need to specify the type. We have also added the size of the carousel which represents the spacing between carousel dots (or lines), we have three sizes: Small, Medium and Large. Medium is the default.

  1. Carousel Dot State

    Backdrop(
        modifier = Modifier.padding(YassirTheme.spacing.spacing0_5), // optional
        backDropType =  BackdropType.EmptyState(
            illustrationResIds = listOf(
                IllustrationInfo(
                    R.drawable.flag_algeria_rect,
                    message = "Top up 1",
                    description = "check 1",
                    subtitle = "subtitle 1", //optional
                ), IllustrationInfo(
                    R.drawable.flag_uae_rect,
                    message = "Top up 2",
                    description = "check 2",
                    subtitle = "subtitle 2", //optional
                ), IllustrationInfo(
                    R.drawable.flag_south_africa_rect,
                    message = "Top up 3",
                    description = "check 3",
                    subtitle = "subtitle 3", //optional
                )
            ),
    -       carouselIndicatorType = CarouselIndicatorType.Black,
            carouselIndicatorStyle = CarouselIndicatorStyle.Dot,  // optional
    +       carouselIndicatorSize = CarouselIndicatorSize.Medium, // optional
        ),
        backdropHeaderItem = BackdropHeaderItem(
          title = "Title",
          subtitle = "Subtitle",
          tabsList = tabsList,
          onBackClick = {},
        ), // optional
        primaryAction = ButtonAction(
            text = "Primary Action",
            startIconResId = null, //optional
            endIconResId = null, //optional
            onClick = {}
        ), // optional
        secondaryAction = ButtonAction(
            text = "Secondary Action",
            startIconResId = null, //optional
            endIconResId = null, //optional
            onClick = {}
        ), // optional
        tertiaryAction = ButtonAction(
            text = "Teritary Action",
            startIconResId = null, //optional
            endIconResId = null, //optional
            onClick = {}
        ), // optional
        isVisible = true, // optional
        screenState = ScreenState.FullScreen, // optional
        windowInsets = WindowInsets(0, 0, 0, 0), // optional
        containerColor = YassirTheme.colors.surfaceNeutralHigh, // optional
        isSecondaryButtonNegative = false, // optional
        sheetState = SheetState(
            skipPartiallyExpanded = true,
            density = LocalDensity.current,
            initialValue = SheetValue.Expanded
        ), // optional
        onDismissRequest = {},
        onCloseClick = null // optional
    )
    

  2. Carousel Line State

    Backdrop(
        modiefier = Modifier.padding(YassirTheme.spacing.spacing0_5), // optional
        backDropType =  BackdropType.EmptyState(
            illustrationResIds = listOf(
                IllustrationInfo(
                    R.drawable.flag_algeria_rect,
                    message = "Top up 1",
                    description = "check 1"
                ), IllustrationInfo(
                    R.drawable.flag_uae_rect,
                    message = "Top up 2",
                    description = "check 2"
                ),  IllustrationInfo(
                    R.drawable.flag_south_africa_rect,
                    message = "Top up 3",
                    description = "check 3",
                )
            ),
    -       carouselIndicatorType = CarouselIndicatorType.Black,
            carouselIndicatorStyle = CarouselIndicatorStyle.Line,  // optional
    +       carouselIndicatorSize = CarouselIndicatorSize.Medium,  // optional
        ),
        backdropHeaderItem = BackdropHeaderItem(
          title = "Title",
          subtitle = "Subtitle",
          tabsList = tabsList,
          onBackClick = {},
        ), // optional
        primaryAction = Action(
            text = "Primary Action",
            startIconResId = null, //optional
            endIconResId = null, //optional
            onClick = {}
        ), // optional
        secondaryAction = Action(
            text = "Secondary Action",
            startIconResId = null, //optional
            endIconResId = null, //optional
            onClick = {}
        ), // optional
        tertiaryAction = Action(
            text = "Teritary Action",
            startIconResId = null, //optional
            endIconResId = null, //optional
            onClick = {}
        ), // optional
        isVisible = true, // optional
        screenState = ScreenState.FullScreen, // optional
        windowInsets = WindowInsets(0, 0, 0, 0), // optional
        containerColor = YassirTheme.colors.surfaceNeutralHigh, // optional
        sheetState = SheetState(
            skipPartiallyExpanded = true,
            density = LocalDensity.current,
            initialValue = SheetValue.Expanded
        ), // optional
        onDismissRequest = {  }
    )
    

DatePicker #

Following changes were done to DatePicker:

  • calendarStart and calendarEnd types were changed from CalendarMonth to CalendarDay, to enable more flexibility in selecting the range of dates available for the user to pick. Please note that the day property is optional.
DatePicker(
    modifier = Modifier,
    properties = DatePickerProperties(
        primaryAction = ButtonAction(text = "Primary Action",onClick = { },),
        secondaryAction = ButtonAction(text = "Secondary Action",onClick = {}, ),
        startDayOfWeek = Weekday.WEDNESDAY,
        startDayOfWeekend = Weekday.FRIDAY,
-       calendarStart = CalendarMonth(month = Calendar.FEBRUARY, year = 2023),
+       calendarStart = CalendarDay(day = 3, month = Calendar.FEBRUARY, year = 2023), //day is optional
-       calendarEnd = CalendarMonth(month = Calendar.NOVEMBER, year = 2035),
+       calendarEnd = CalendarDay(day= 15, month = Calendar.NOVEMBER, year = 2035), //day is optional
        selectCalendarMonth = CalendarMonth(month = Calendar.OCTOBER, year = 2024),
    ),
    selectionMode = DateSelectionMode.Single(
        isScrollable = false,
        isTodayMarked = false,
        timeSelectionProperties = TimePickerProperties(), //note that there were breaking changes to TimePickerProperties in this release, also announced here below
    ),
    selectedDates = emptyList(),
    updateDateSelection = { newDates ->  },
    onDismissRequest = { },
)

TimePicker #

Following changes were done to TimePicker:

  • onChevronIconClick was renamed as onBackIconClick and was moved from TimePickerProperties to become a property for the TimePicker itself. Please note that if this is not passed, the chevron icon won´t be shown.
  • onApply was renamed to onApplyButtonClick
  • onCancel was renamed to onCancelButtonClick
TimePicker(
    timePickerProperties = TimePickerProperties(
        timeFormat = TimeFormat.HOUR_24,
        startTime = Calendar.getInstance(),
-       onChevronIconClick = { onShowDialogChange(false) }               
   ),
   onDismissRequest = { onShowDialogChange(false) },
+  onBackIconClick = { onShowDialogChange(false) },
-  onApply = { calendar -> },
+  onApplyButtonClick = { calendar -> },
-  onCancel = { onShowDialogChange(false) },
+  onCancelButtonClick = { onShowDialogChange(false) },
)

MonthPicker #

Following change was done to MonthPicker:

  • onBackIconClick was added to handle back navigation. Please note that if this is not passed, the chevron icon won´t be shown.
MonthPicker(
    startMonth = 4,
    endMonth = 11,
    onDismissRequest = { showDialog = false },
    selectedMonth = 5,
    onMonthSelected = {
        showDialog = false
        selectedMonth.value = it
    },
+   onBackIconClick = { showDialog = false },
)

YearPicker #

Following change was done to YearPicker:

  • onBackIconClick was added to handle back navigation. Please note that if this is not passed, the chevron icon won´t be shown.
YearPicker(
    startYear = 2020,
    endYear = 2066,
    onDismissRequest = { showDialog = false },
    selectedYear = selectedYear.value,
    onYearSelected = {
        showDialog = false
        selectedYear.value = it
    },
+   onBackIconClick = { showDialog = false },
)

DateSelectionField - DateFieldSelectionProperties #

Following changes was done to DateFieldSelectionProperties signature (used in DateSelectionField):

  • calendarStart and calendarEnd types were changed from CalendarMonth to CalendarDay, to enable more flexibility in selecting the range of dates available for the user to pick. Please note that the day property is optional.
DateSelectionField(
    label = "Select a date",
    enabled = true,
    hasError = false,
    hint = hint,
    datePickerProperties = DateFieldSelectionProperties(
        startDayOfWeek = Weekday.MONDAY,
        startDayOfWeekend = Weekday.SATURDAY,
-       calendarStart = CalendarMonth(dmonth = Calendar.JANUARY, year = 2022),
+       calendarStart = CalendarDay(ay= 1, month = Calendar.JANUARY, year = 2022), //day is optional
-       calendarEnd = CalendarMonth(month = Calendar.DECEMBER, year = 2026),
+       calendarEnd = CalendarDay(day = 15, month = Calendar.DECEMBER, year = 2026), //day is optional
        selectCalendarMonth = CalendarMonth(month = Calendar.JANUARY, year = 2024),
        showActionButtons = showActionButtons,
    ),
    fieldProperties = DateInputFieldProperties(),
    onDateChanged = { date ->
      Toast.makeText(context, "Date changed: $date", Toast.LENGTH_SHORT).show()
    },
)

Animated Increment Button #

Added isLoading state to animated type

DefaultIncrementButton(
  modifier = modifier, // optional
  enabled = areButtonsEnabled, // optional
  minValue = 1, // optional
  maxValue = 5, // optional
  defaultValue = 1, // optional
  onTrashClicked = { 
    Toast.makeText(context, "Trash Clicked", Toast.LENGTH_SHORT).show() 
  }, // optional
  type = IncrementButtonType.Animated(
+   isLoading = true,
    isAddOnly = false,
    elevationStyle = ElevationStyle.Light1,
    shadowPosition = ShadowPosition.Bottom,
  ) // pass options if needed
)

Migrate from Sefar 0.12.0 to 0.13.0 #

You will encounter the following breaking changes while you migrate:

In Banner we used to have the same style class called BannerState for both types of Banner. And since sometimes some styles does not exist in one of the types(for example Alternatice available only in FullWiddthBanner), now we have a seperate style classes for each type. For Boxed Banner we will have BoxedBannerState, and for Full Width Banner it will be FullWidthBannerState.

Before #
1.Boxed Banner #
Banner(
   bannerType = BannerType.Boxed(
      label = "Label", // optional
      bodyText = "This is the subtitle text of banner.", // optional
      style = BannerState.Default, // ❌ old
      captionText = "This is the caption text of banner", // optional
      captionIconRes = R.drawable.ic_alert_circle, // optional
      leadingIconRes = R.drawable.ic_alert_circle, // optional
      trailingIconRes = R.drawable.ic_small_x, // optional
      isElevated = false, // optional
      primaryBannerAction =
          BannerAction(
              text = "Primary Action",
              isEnabled = false,  // optional
              onClick = { /* action */  }
           ),  // optional
      secondaryBannerAction =
          BannerAction(
              text = "Secondary action",
              isEnabled = false,  // optional
              onClick = {  /* action */  },
            )
        ),  // optional
      trailingIconOnClick = {  /* action */ }
)
2.Full Width Banner #
Banner(
    bannerType = BannerType.FullWidth(
        text = "This is the text of banner",
        style = BannerState.Positive, // ❌ old
        iconRes = R.drawable.ic_alert_circle,  // optional
        isElevated = true  // optional
    )
)
After #
1.Boxed Banner #
Banner(
   bannerType = BannerType.Boxed(
      label = "Label", // optional
      bodyText = "This is the subtitle text of banner.", // optional
      style = BoxedBannerState.Default, // ✅ New
      captionText = "This is the caption text of banner", // optional
      captionIconRes = R.drawable.ic_alert_circle, // optional
      leadingIconRes = R.drawable.ic_alert_circle, // optional
      trailingIconRes = R.drawable.ic_small_x, // optional
      isElevated = false, // optional
      primaryBannerAction =
          BannerAction(
              text = "Primary Action",
              isEnabled = false,  // optional
              onClick = { /* action */  }
           ),  // optional
      secondaryBannerAction =
          BannerAction(
              text = "Secondary action",
              isEnabled = false,  // optional
              onClick = {  /* action */  },
            )
        ),  // optional
      trailingIconOnClick = {  /* action */ }
)
2.Full Width Banner #
Banner(
    bannerType = BannerType.FullWidth(
        text = "This is the text of banner",
        style = FullWidthBannerState.Positive, // ✅ New
        iconRes = R.drawable.ic_alert_circle,  // optional
        isElevated = true  // optional
    )
)

Backdrop - CustomState #

Modifier was removed from lambda and a new optional requiredHeight property was adeed. If you´re using a custom state, add a requiredHeight if you want to set a custom height for your custom content, Otherwise, it will default to a height of 1/3 of the screen´s size.

Before #
Backdrop(
    backDropType =  BackdropType.CustomState(
        customContent = { modifier ->
            // create custom component
            
        }
    ),
    onDismissRequest = {  }
)
After #
Backdrop(
    backDropType =  BackdropType.CustomState(
        requiredHeight = 600.dp,
        customContent = {
            // create custom component
            
        }
    ),
    onDismissRequest = {  }
)

Backdrop - Actions #

In the Backdrop component startIcon and endIcon are added to the actions (primaryAction,secondaryAction,tertiaryAction).

Before #
Backdrop(
  // Other backdrop properties,
  primaryAction: ButtonAction(
    text = "Primary Button",
    onClick = {}
  ),
  secondaryAction: ButtonAction(
    text = "Secondary Button",
    onClick = {}
  ),
  tertiaryAction: ButtonAction(
    text = "Tertiary Button",
    onClick = {}
  ),
  // Other backdrop properties
)
After #
Backdrop(
  // Other backdrop properties,
  primaryAction: ButtonAction(
    text = "Primary Button",
    startIconResId = null,  //optional
    endIconResId = null,  //optional
    onClick = {}
  ),
  secondaryAction: ButtonAction(
    text = "Secondary Button",
    startIconResId = null,  //optional
    endIconResId = null,  //optional
    onClick = {}
  ),
  tertiaryAction: ButtonAction(
    text = "Tertiary Button",
    startIconResId = null, //optional
    endIconResId = null,  //optional
    onClick = {}
  ),
  // Other backdrop properties
)

Migrate from Sefar 0.11.0 to 0.12.0 #

Watchout for the next list of breaking changes while you migrate:

Avatar #

badge is removed in all the three types of avatars and replaced by badgeType which is an AvatarBadgeType.

Before #
1.Initials Avatar #
InitialsAvatar(
  modifier = Modifier,
  name = "Foo Bar",
  size = AvatarSize.Large,
  isFocused = true,
  isElevated = true,
  badge = {},
  hasTwoInitials = false
)
2.Image Avatar #
ImageAvatar(
  modifier = Modifier,
  imageUrl = null,
  resourceId = R.drawable.ic_avatar,
  size = AvatarSize.Medium,
  isFocused = false,
  isElevated = true,
  badge = {},
)
3.Icon Avatar #
IconAvatar(
  size = AvatarSize.Small,
  modifier = Modifier,
  iconRes = DrawableR.ic_user,
  isFocused = false,
  isElevated = true,
  badge = {},
)
After #
1.Initials Avatar #
InitialsAvatar(
  modifier = Modifier,
  name = "Foo Bar",
  size = AvatarSize.Large,
  isFocused = true,
  isElevated = true,
  badgeType = AvatarBadgeType.OnlineIndicatorBadge(isOnline = true),
  hasTwoInitials = false
)
2.Image Avatar #
ImageAvatar(
  modifier = Modifier,
  imageUrl = null,
  resourceId = R.drawable.ic_avatar,
  size = AvatarSize.Medium,
  isFocused = false,
  isElevated = true,
  badgeType = AvatarBadgeType.VerifiedBadge,
)
3.Icon Avatar #
IconAvatar(
  size = AvatarSize.Small,
  modifier = Modifier,
  iconRes = DrawableR.ic_user,
  isFocused = false,
  isElevated = true,
  badgeType = AvatarBadgeType.None,
)

Profile #

In Profile badge is removed in all the three types of profile and replaced by badgeType which is a ProfileBadgeType.

Before #
1.Image Profile #
ImageProfile(
    modifier = Modifier,
    imageUrl = "",
    resourceId = R.drawable.ic_avatar,
    size = ProfileSize.Small,
    withBorder = false, 
    badge = {},
)
2.Icon Profile #
IconProfile(
    modifier = Modifier,
    size = ProfileSize.Medium,
    withBorder = false,
    badge = {},
)
3.Initials Profile #
InitialsProfile(
    name = "Foo Bar",
    modifier = Modifier,
    size = ProfileSize.Large,
    withBorder = false,
    badge = {},
    hasTwoInitials = false,
)
After #
1.Image Profile #
ImageProfile(
    modifier = Modifier,
    imageUrl = "",
    resourceId = R.drawable.ic_avatar,
    size = ProfileSize.Small,
    withBorder = false, 
    badgeType = ProfileBadgeType.VerifiedBadge,
)
2.Icon Profile #
IconProfile(
    modifier = Modifier,
    size = ProfileSize.Medium,
    withBorder = false, 
    badgeType = ProfileBadgeType.EditBadge(onEditClick = { }),
)
3.Initials Profile #
InitialsProfile(
    name = "Foo Bar",
    modifier = Modifier,
    size = ProfileSize.Large,
    withBorder = false, // optional
    badgeType = ProfileBadgeType.None, 
    hasTwoInitials = false, // optional
)

Badge #

Style name have been Changed from kotlin BadgeStyleType.Contrast to BadgeStyleType.Contrasty, to match figma´s naming

ListItem #

Updated the List Item to v1.3.0 by doing the following:

  • Removed the Large size
  • Added Image type as a leading element
  • Added an option to show a Tag below the secondary text
After #
    val contentProperties =
        ListItemContentProperties(
            .
            .
            .
            tagProperties = TagProperties(
                text = "test tag",
                tagStyle = TagStyle.Neutral,
                size = YassirTagSize.Medium,
            ),
            .
            .
            .
        )

    val visualConfig =
        ListItemVisualConfig(
            .
            .
            size = ListItemSize.Medium, // optional,  ListItemSize.Large is no longer available
            .
            .
        )

    ListItem(
        .
        contentProperties = contentProperties,
        transactionProperties = ListItemTransactionProperties(), // optional
        visualConfig = visualConfig, // optional
        .
        .
    )

Tag #

All of the following have been removed and replaced with a single Tag component. These variants were already deprecated for a while and were planned to be removed in this version. Please see the new implementation NeutralTag, PositiveTag, NegativeTag, WarningTag, InformativeTag, PrimaryTag, SecondaryTag

Before #
NeutralTag (
  modifier = Modifier, // optional
  .
  .
)
PositiveTag (
  modifier = Modifier, // optional
  .
  .
)
NegativeTag (
  modifier = Modifier, // optional
  .
  .
)
WarningTag (
  modifier = Modifier, // optional
  .
  .
)
InformativeTag (
  modifier = Modifier, // optional
  .
  .
)
PrimaryTag (
  modifier = Modifier, // optional
  .
  .
)
SecondaryTag (
  modifier = Modifier, // optional
  .
  .
)
After #
Tag(
    modifier = Modifier, // optional
    tagProperties = TagProperties(
        text = "12:20", // optional
        tagStyle = TagStyle.Neutral, //(Fee free to pass any of the styles available here)
        val isElevated = false, // optional
        val isAlternativeStyle = false, // optional
        val startIconResId = null, // optional
        size = YassirTagSize.ExtraLarge, // optional
    ),
)

Migrate from Sefar 0.2.9 to 0.11.0 #

Below is presented the list of the breaking changes which may effect the consumers of the library:

Bar Chart & Line Chart: #

Both Bar Chart and Line Chart have parameter type changes.

Initially xAxisValues and yAxisValues where of type List and values were allowed to be either AxisValue.Numeric or AxisValue.Categorical. Now, xAxisValues are of type List and yAxisValues are of type List. yAxisValues can no longer be categorical, only numeric.

Please refer to the updated usage section of Charts to see a code example.

General Illustrations Name Changes: #

Before #
GeneralIllustrations.GlobeExclamationMarkPaperplane
After #

Please note case changes in letter B of Dashboard

GeneralIllustrations.GlobeExclamationMarkInactivePaperPlane

Buttons: #

There was a problem with modifiers of buttons that were applied twice. So if you added padding of 8.dp, it would apply it twice and you will have a padding of 16.dp. In this new version, we fixed this problem. So, if you were using our buttons and applying modifiers to them please review them to make sure you have the same UI.

System Icons #

Dashboard icons were renamed, so please check the following before and after (names are listed respectively):

Before #
SystemIcons.DashBoard
SystemIcons.DashBoard1
SystemIcons.DashBoard1Filled
After #

Please note case changes in letter B of Dashboard

SystemIcons.LineChart
SystemIcons.Dashboard
SystemIcons.DashboardFilled

Logo Icons Removed: #

Country Flags in LogosIcons were removed. So all the following will no longer be avalable

LogosIcons.AlgeriaRectangular
LogosIcons.AlgeriaRound
LogosIcons.FranceRectangular
LogosIcons.FranceRound
LogosIcons.MoroccoRectangular
LogosIcons.MoroccoRound
LogosIcons.SenegalRectangular
LogosIcons.SenegalRound
LogosIcons.SouthAfricaRectangular
LogosIcons.TunisiaRectangular
LogosIcons.TunisiaRound
LogosIcons.UAERectangular
LogosIcons.UAERound

RatingBar #

Added a property to disable the double tap event on the Rating bar (to optionally diable half star ratings)

Before #
var rating by remember { mutableFloatStateOf(0f) }

RatingBar(
    modifier = Modifier.padding(16.dp), //optional
    onRatingChange = { newRating -> rating = newRating }
)
After #
var rating by remember { mutableFloatStateOf(0f) }

RatingBar(
    modifier = Modifier.padding(16.dp), //optional
    allowDoubleTap = false, //optional
    onRatingChange = { newRating -> rating = newRating }
)

Generic Input #

New Parameter Added called isInteractive. The parameter is true by default. If you don´t want your field to show the keyboard or to appear in focused state when tapped on, you can set it to false. Example Usecase: If you want the generic Field to be clickable and to direct the user to another action or page, you can set this property to false and add a clickable modifier.

GenericInput(
  modifier = Modifier.clickable {
    Log.d("GenericInputField", "Clicked on GenericInput")
  }
  .
  .
  .
  .
  isInteractive = true, // optional
  .
  .
  .
  .
)

BottomNavigationBarItem #

BottomNavigatioBar item should have a BadgeType now instead of only raw text, this will allow to show a text badge or a dot badge.

Before #
val bottomNavigationBarList = listOf(
        BottomNavigationBarItem(
            text = "Tab",
            iconRes = R.drawable.ic_alert_circle,
            onClick = {  }
        ),
        BottomNavigationBarItem(
            textResId = R.string.tab_string,
            iconRes = R.drawable.ic_lock,
            badgeText = null,
            onClick = {  },
        ),
        BottomNavigationBarItem(
            text = "Tab",
            iconRes = R.drawable.ic_coins_hand,
            badgeText = "2"
            onClick = {  },
        )
    )

BottomNavigationBar(
  list = bottomNavigationBarList,
  selectedItemIndex = 1,
  onItemSelected = { }
)
After #
val bottomNavigationBarList = listOf(
        BottomNavigationBarItem(
            text = "Tab",
            iconRes = R.drawable.ic_alert_circle,
            onClick = {   }
        ),
        BottomNavigationBarItem(
            textResId = R.string.tab_string,
            iconRes = R.drawable.ic_lock,
            badgeType = BadgeType.TextBadge("2"),
            onClick = {   },
        ),
        BottomNavigationBarItem(
            text = "Tab",
            iconRes = R.drawable.ic_coins_hand,
            badgeType = BadgeType.DotBadge
            onClick = {   },
        )
    )

BottomNavigationBar(
  list = bottomNavigationBarList,
  selectedItemIndex = 1,
  onItemSelected = { }
)

Migrate from Sefar 0.2.8 to 0.2.9 #

Below is presented the list of the breaking changes which may effect the consumers of the library:

TagStyle #

TagStyle´s location has been changed. SO if you were using it you will have to re-import it.

Before #
import com.yassir.android.yassir_design_system.designsystem.components.tags.internal.TagStyle
After #
import com.yassir.android.yassir_design_system.designsystem.components.tags.TagStyle

Illustrations #

Before #
GeneralIllustrations.GiftUserContact
After #
GeneralIllustrations.GiftPhoneUserContactBig

CheckboxGroup & RadioGroup removal of various styles: #

You will no longer be able to select checkboxStyle or radioButtonStyle to change the size of the selectors. There´s only one unifies size now.

Before #
CheckboxGroup(
  modifier = Modifier,
  onStateChange = {checkBoxGroupState -> },
  topLevelCheckbox = IndeterminateCheckboxItem(
    title = "Toppings",
    description = "All the toppings"
  ),
  checkboxes = listOf(
    CheckboxItem(title = "Pepperoni", description = "spicy salami seasoned with paprika"),
    CheckboxItem(title = "Extra cheese", description = "extra cheese on your pizza!"),
  ),
  isGroupEnabled = true,
  checkboxStyle = CheckboxStyle.Large
)

RadioGroup(
  modifier = Modifier,
  onItemSelection = { intValue ->  },
  items = leadingRadioGroupList,
  selectedItemIndex = 0,
  isGroupEnabled = true
  radioButtonStyle = RadioButtonStyle.Small
)
After #
RadioGroup(
  modifier = Modifier,
  onItemSelection = { intValue ->  },
  items = leadingRadioGroupList,
  selectedItemIndex = 0,
  isGroupEnabled = true 
)
CheckboxGroup(
  modifier = Modifier,
  onStateChange = {checkBoxGroupState -> },
  topLevelCheckbox = IndeterminateCheckboxItem(
    title = "Toppings",
    description = "All the toppings"
  ),
  checkboxes = listOf(
    CheckboxItem(title = "Pepperoni", description = "spicy salami seasoned with paprika"),
    CheckboxItem(title = "Extra cheese", description = "extra cheese on your pizza!"),
  ),
  isGroupEnabled = true,
)

Switch - removal of small toggle type #

Small Variant has been removed, only Large variant stays so need to specify type

Before #
  Switch(
    enabled = true,
    checked = true,
    type = ToggleType.LargeSwitch(isIconVisible = true, title = "ON"),
    onToggle = {},
  )
After #
  Switch(
    enabled = true,
    checked = false,
    isIconVisible = false,
    title = "OFF",
    onToggle = {},
  )

Snackbar #

Removed optional ´displayDuration´, duration now is 6000L

Before #
Snackbar(
    message = "This is a snackbar message",
    actionLabel = "Retry",
    onActionClick = { },
    iconResId = R.drawable.ic_alert_circle,
    displayDuration = 5000L, // optional, default is 5000 milliseconds (5 seconds)
    onDismiss = { },
    action2Label = "Undo", 
    onAction2Click = {  },
)
After #
Snackbar(
    message = "This is a snackbar message",
    actionLabel = "Retry",
    onActionClick = {  },
    iconResId = R.drawable.ic_alert_circle,
    onDismiss = { },
    action2Label = "Undo",
    onAction2Click = { },
)

Migrate from Sefar 0.2.7.3 to 0.2.8 #

Below is presented the list of the breaking changes which may effect the consumers of the library:

Button TrailingElementType in ListItem: #

add leadingIconResId, trailingIconResId, loading and isElevated to Button.

Before #
 data class Button(
    val modifier: Modifier = Modifier,
    val onClick: () -> Unit,
    val text: String,
    val buttonType: ButtonType = ButtonType.Primary,
) : TrailingElementType()
After #
data class Button(
    val modifier: Modifier = Modifier,
    val text: String,
    val buttonType: ButtonType = ButtonType.Primary,
    val loading: Boolean = false,
    val isElevated: Boolean = false,
    @DrawableRes val leadingIconResId: Int? = null,
    @DrawableRes val trailingIconResId: Int? = null,
    val onClick: () -> Unit,
) : TrailingElementType()

CustomState in backdrop: #

Passed Modifier in customContent to make sure content is properly scrollable and aligned and have sticky footer bottom and ensure full state/contained in backdrop.

Before #
    data class CustomState(
    val isElevatedFooter: Boolean = false,
    val customContent: @Composable (() -> Unit)? = null,
) : BackdropType()
After #
data class CustomState(
    val isElevatedFooter: Boolean = false,
    val customContent: @Composable ((Modifier) -> Unit)? = null,
) : BackdropType()

Icons #

Icon from Communication library had name change from ´StarSmallFilled´ to ´StarSmallFull´

Before #
CommunicationIcons.StarSmallFilled
After #
CommunicationIcons.StarSmallFull

Icons from Logos library had names changed as follows:

Before #
LogosIcons.Viper
LogosIcons.ViperMonotone
LogosIcons.TicTok
LogosIcons.TicTokMonotone
LogosIcons.Twitter
LogosIcons.TwitterMonotone
LogosIcons.FacebookMessage
LogosIcons.FacebookMessageMonotone
LogosIcons.UAEeRound
After #
LogosIcons.Viber
LogosIcons.ViberMonotone
LogosIcons.TikTok
LogosIcons.TikTokMonotone
LogosIcons.X
LogosIcons.XMonotone
LogosIcons.FacebookMessenger
LogosIcons.FacebookMessengerMonotone
LogosIcons.UAERound

Icons from Communication library had names changed as follows:

Before #
CommunicationIcons.Marketing
After #
CommunicationIcons.Speaker

Migrate from Sefar 0.2.7.2 to 0.2.7.3 #

Below is presented the list of the breaking changes which may effect the consumers of the library

PhoneInput #

2 new parameters where added:

  • isCountrySelectionEnabled a boolean to determine whether a tapping only the flag opens a backdrop with country selection or not.
  • isCountryCodeTextEnabled a boolean flag to make country code text is dimmed and disabled or enabled.

Migrate from Sefar 0.2.6 to 0.2.7 #

Below is presented the list of the breaking changes which may effect the consumers of the library

Snackbar #

The Snackbar size has been removed, now it has a fixed height of 44.dp, in adddition, the Snackbar now can accept two actions rather than only one action.

Snackbar Before #
Snackbar(
    modifier = Modifier, // optional: passed as is
    message = "Message to show to users", // set the snackbar message
    actionLabel = null, // optional
    onActionClick = {}, // optional
    iconResId = null, // optional,
    size = SnackbarSize.Medium, //optional
    displayDuration = 5000L, // optional
    onDismiss = {}, // optional
)
Snackbar After #
Snackbar(
    modifier = Modifier, // optional: passed as is
    message = "Message to show to users", // set the snackbar message
    actionLabel = null, // optional
    onActionClick = {}, // optional
    iconResId = null, // optional,
    displayDuration = 5000L, // optional
    onDismiss = {}, // optional,
    action2Label = null, // optional
    onAction2Click = {}, // optional
)

LineChart #

  • AxisValue & Dataset classes that are used as property types in LineChart have changed locations so you might want to remove their imports and add them again correctly.

SizeConstants #

The class SizeConstants is no longer available for consumers of Sefar. Please only consider using spacings supported in our theme example: YassirTheme.spacing.spacing1 and if you don´t find a value in our supported spacings that is the same size you need then the size you´re looking for is not supported by Sefar so in that case please add it to your own code base as a constant.

ListItem #

Before #
ListItem(
  modifier = Modifier.padding(YassirTheme.spacing.spacing3), // optional
  title = "Sample Title",
  description = "description",
    leading = LeadingElementType.Icon(
      iconRes = DrawableR.ic_coins_hand,
      tint = YassirTheme.colors.labelNeutralDefault,
    ), // optional
    trailing = TrailingElementType.CheckBox(
      selectionState = trailingCheckBoxState,
      onClick = {},
    ), // optional
    description = "description", // optional
    upperDescription = "upperDescription", // optional
    locale = currentLocale(), // optional
    onClickLabel = "", // optional
    isSelected = true, // optional
    isEnabled = true, // optional
    onClick = {
        Toast.makeText(context, "List Item was clicked", Toast.LENGTH_SHORT).show()
    } // optional
)
After #
    val contentProperties =
        ListItemContentProperties(
            title = "Title",
            description = "Description", // optional
            leading = LeadingElementType.Icon(
                iconRes = DrawableR.ic_ds_coins_hand,
                tint = YassirTheme.colors.labelNeutralDefault,
            ), // optional
            trailing = TrailingElementType.CheckBox(
                selectionState = trailingCheckBoxState,onClick = {},
            ), // optional
            upperDescription = "upperDescription", // optional
            onClickLabel = "", // optional
        )

    val transactionProperties =
        ListItemTransactionProperties(
            formattedAmount = "$ 54.00", // optional
            transactionType = TransactionType.Incoming, // optional
            transactionStatus = TransactionStatus.Pending, // optional
            currencyHidden = true, // optional
            transactionDateTime = Date(), // optional
        )

    val visualConfig =
        ListItemVisualConfig(
            size = ListItemSize.Medium, // optional
            isSelected = true, // optional
            isEnabled = true, // optional
            showDivider = true, // optional
            showOutline = true, // optional
            styleOverrides = ListItemStyleOverrides(
                roundedCornersSize = SpacingKey.SPACING_0, // optional
                verticalPaddingKey = SpacingKey.SPACING_1, // optional
                horizontalPaddingKey = SpacingKey.SPACING_1, // optional
                descriptionTextColorKey = YassirColorSchemeKey.LabelNeutralDefault, // optional
                titleTextColorKey = YassirColorSchemeKey.LabelPrimary, // optional
                itemBackgroundColorKey = YassirColorSchemeKey.SurfaceNeutralDefault, // optional
            ) // optional
        )

    ListItem(
        modifier = Modifier, // optional
        contentProperties = contentProperties,
        transactionProperties transactionProperties, // optional
        visualConfig = visualConfig, // optional
        locale = currentLocale(), // optional
        onClick = {
            Toast.makeText(context, "List Item was clicked", Toast.LENGTH_SHORT).show()
        } // optional
    )

Migrate from Sefar 0.2.5 to 0.2.6 #

Below is presented the list of the breaking changes which may effect the consumers of the library

CodeInput #

Please note that the valid types of codeType property have been changed for PIN code and OTP code. Please see below examples:

PIN CODE Before #
CodeInput(
  modifier = Modifier, // optional
  codeType = CodeType.PIN_CODE,
  label = "PIN Code", // optional
  isError = false, // optional
  isEnabled = true, // optional
  clearCode = false, // optional
  autoFocus = true, // optional
  codeLength = CodeInputDefaults.LENGTH, // optional
  spaceBetweenCodeCells = YassirTheme.spacing.spacing2, // optional
  hint = AnnotatedString(hintText), // optional
  onHintClick = {}, // optional
  resetErrorState = {}, // optional
  onCodeFilled = { code ->
    /* handle entered PIN code */
  },
  colors = YassirTheme.colors // optional
)
PIN CODE After #
CodeInput(
  modifier = Modifier, // optional
  codeType = CodeType.PinCode,
  label = "PIN Code", // optional
  isError = false, // optional
  isEnabled = true, // optional
  clearCode = false, // optional
  autoFocus = true, // optional
  codeLength = CodeInputDefaults.LENGTH, // optional
  spaceBetweenCodeCells = YassirTheme.spacing.spacing2, // optional
  hint = AnnotatedString(hintText), // optional
  onHintClick = {}, // optional
  resetErrorState = {}, // optional
  onCodeFilled = { code ->
    /* handle entered PIN code */
  },
  colors = YassirTheme.colors // optional
)
OTP CODE Before #
CodeInput(
  modifier = Modifier
    .align(Alignment.CenterHorizontally)
    .padding(top = YassirTheme.spacing.spacing4), // optional
  codeType = CodeType.OTP_CODE,
  isError = false, // optional
  isEnabled = true, // optional
  clearCode = false, // optional
  autoFocus = true, // optional
  codeLength = 6, // optional
  spaceBetweenCodeCells = YassirTheme.spacing.spacing1_5, // optional
  hint = AnnotatedString(hintText), // optional
  onHintClick = {}, // optional
  resetErrorState = { isError = false }, // optional
  onCodeFilled = { code ->
    /* handle entered OTP code */
  },
  colors = YassirTheme.colors, // optional
  label = "OTP Code" // optional
)
OTP CODE Before #
CodeInput(
  modifier = Modifier
    .align(Alignment.CenterHorizontally)
    .padding(top = YassirTheme.spacing.spacing4), // optional
  codeType = CodeType.OtpCode(
    initialCode = "456757" //optional
  ),
  isError = false, // optional
  isEnabled = true, // optional
  clearCode = false, // optional
  autoFocus = true, // optional
  codeLength = 6, // optional
  spaceBetweenCodeCells = YassirTheme.spacing.spacing1_5, // optional
  hint = AnnotatedString(hintText), // optional
  onHintClick = {}, // optional
  resetErrorState = { isError = false }, // optional
  onCodeFilled = { code ->
    /* handle entered OTP code */
  },
  colors = YassirTheme.colors, // optional
  label = "OTP Code" // optional
)

Migrate from Sefar 0.2.3 to 0.2.5 #

Below is presented the list of the breaking changes which may effect the consumers of the library

TimePicker #

File has been moved and properties of the component have been combined under ´TimePickerProperties´ object, so re-add the import and check the following example:

Before #
TimePicker(
    timeFormat = if (is24HFormat) TimeFormat.HOUR_24 else TimeFormat.AM_PM,
    minutesIncrement = minutesIncrement,
    onDismissRequest = { onShowDialogChange(false) },
    onApply = { uno ->
        onApply(uno)
        onShowDialogChange(false)
    },
    onSnappedTime = { uno, _ -> uno.get(Calendar.HOUR_OF_DAY) },
    onCancel = { onShowDialogChange(false) }
)
After #
TimePicker(
    modifier = Modifier.withTestPrefix("time_picker_screen"),
    timePickerProperties = TimePickerProperties(
        timeFormat = if (is24HFormat) TimeFormat.HOUR_24 else TimeFormat.AM_PM,
        minutesIncrement = minutesIncrement,
        onSnappedTime = { uno, _ -> uno.get(Calendar.HOUR_OF_DAY) },
    ),
    onDismissRequest = { onShowDialogChange(false) },
    onApply = { uno ->
        onApply(uno)
        onShowDialogChange(false)
    },
    onCancel = { onShowDialogChange(false) }
)

BottomNavigationBar #

Properties have been changed:

Before #
BottomNavigationBar(
  list = bottomNavigationBarList,
  initialSelectedItemIndex = 1, // optional
  colors = YassirColorScheme.colors // optional
)
After #
BottomNavigationBar(
  list = bottomNavigationBarList,
  selectedItemIndex = 1, // optional
  onItemSelected = { }
)

Migrate from Sefar 0.2.2.2 to 0.2.3 #

Below is presented the list of the breaking changes which may effect the consumers of the library

PhoneInput #

  1. Added arguments to customize Country Backdrop in Phone Input, like “countryBackdropTitle”, “searchBackdropPlaceholder” “backdropHintText”
  2. Changed the logic of passing the initial selected country - now it is needed to pass a String with Region Code
  3. Changed logic of setting a list of countries for the Phone Input. Now it is divided into 3 different lists, more about it usages and the definition of the types can be found in the Sefar Phone Input documentation

Before: #

PhoneInput(
  modifier = Modifier.padding(YassirTheme.spacing.spacing3), // optional
  hint = "Phone Number can't be empty!", // optional
  hasError = true, // optional
  hasLabel = true, // optional
  enabled = true, // optional
  phoneNumber = "", // optional
  isCountrySelectionEnabled = true, // optional
  countriesList = SupportedCountries.entries, // optional
  onPhoneNumberChange = { phoneNumber, isValid -> }, // optional
  initialSelectedCountry = SupportedCountry.ALgeria, // optional
  onHintClick = { /* action */ } // optional,
  onImeAction = { /* action */ } // optional,
)

After #

PhoneInput(
  modifier = Modifier.padding(YassirTheme.spacing.spacing3), // optional
  hint = "Phone Number can't be empty!", // optional
  hasError = true, // optional
  hasLabel = true, // optional
  enabled = true, // optional
  phoneNumber = "", // optional
  isCountrySelectionEnabled = true, // optional
  countriesList = SupportedCountries.entries, // optional
  onPhoneNumberChange = { phoneNumber, isValid -> }, // optional
  initialSelectedCountryRegionCode: String = SupportedCountry.Algeria.regionCode // optional
  countriesBackDropList: CountryCodeListType = CountryCodeListType.SupportedCounties // optional
  countryBackdropTitle: String = "", // optional
  backdropHintText: Int? = R.string.country_backdrop_hint, // optional
  searchBackdropPlaceholder: String? = null,
  onHintClick = { /* action */ } // optional,
  onImeAction = { /* action */ } // optional,
)

MapPin #

  1. YassirMapPin name is changed to MapPin

Before:

fun YassirMapPin(
    mapPinType: MapPinType,
    mapPinDirection: MapPinDirection = MapPinDirection.Up,
    mapPinComponentColor: MapPinComponentColor = MapPinComponentColor.Primary
)

After:

fun MapPin(
    modifier: Modifier = Modifier,
    mapPinType: MapPinType,
    mapPinDirection: MapPinDirection = MapPinDirection.Up,
    mapPinComponentColor: MapPinComponentColor = MapPinComponentColor.Primary
)

Action changes: #

  1. Action name changed to Button Action used in Backdrop and Modal

Before:

fun Modal(
    modifier: Modifier = Modifier,
    modalType: ModalType,
    colors: YassirColorScheme = YassirTheme.colors,
    primaryAction: Action? = null,
    secondaryAction: Action? = null,
    tertiaryAction: Action? = null,
    onDismiss: () -> Unit,
) 

After:

fun Modal(
    modifier: Modifier = Modifier,
    modalType: ModalType,
    colors: YassirColorScheme = YassirTheme.colors,
    primaryAction: ButtonAction? = null,
    secondaryAction: ButtonAction? = null,
    tertiaryAction: ButtonAction? = null,
    onDismiss: () -> Unit,
) 
Backdrop #

Before:

fun Backdrop(
    modifier: Modifier = Modifier,
    backDropType: BackdropType,
    backdropHeaderItem: BackdropHeaderItem? = null,
primaryAction: ButtonAction? = null,
    secondaryAction: ButtonAction? = null,
    tertiaryAction: ButtonAction? = null,
    isVisible: Boolean = false,
    screenState: ScreenState = ScreenState.Contained(),
    windowInsets: WindowInsets = BottomSheetDefaults.windowInsets,
    sheetState: SheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
    onDismissRequest: () -> Unit
)

After:

fun Backdrop(
    modifier: Modifier = Modifier,
    backDropType: BackdropType,
    backdropHeaderItem: BackdropHeaderItem? = null,
    primaryAction: ButtonAction? = null,
    secondaryAction: ButtonAction? = null,
    tertiaryAction: ButtonAction? = null,
    isVisible: Boolean = false,
    screenState: ScreenState = ScreenState.Contained(),
    windowInsets: WindowInsets = BottomSheetDefaults.windowInsets,
    sheetState: SheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
    onDismissRequest: () -> Unit
)