From e663e824b7f37053ee659b998b1fb9355cf6d0b2 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Thu, 13 Nov 2025 00:35:34 +0200 Subject: [PATCH] Add `rectangular` shape to button (#9382) --- src/components/AppLanguageDropdown.tsx | 1 + src/components/Button.tsx | 30 ++++++++++++++++++- src/components/Select/index.tsx | 2 +- src/screens/Search/Shell.tsx | 3 +- src/screens/Settings/AppPasswords.tsx | 5 ++-- src/screens/Settings/LanguageSettings.tsx | 2 +- .../components/ChangeHandleDialog.tsx | 9 ++++-- 7 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/components/AppLanguageDropdown.tsx b/src/components/AppLanguageDropdown.tsx index 9837ce5ced..7ad0928778 100644 --- a/src/components/AppLanguageDropdown.tsx +++ b/src/components/AppLanguageDropdown.tsx @@ -48,6 +48,7 @@ export function AppLanguageDropdown() { })} variant="ghost" color="secondary" + shape="rectangular" style={[ a.pr_xs, a.pl_sm, diff --git a/src/components/Button.tsx b/src/components/Button.tsx index d5b114fae7..4356ec6d38 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -39,7 +39,7 @@ export type ButtonColor = | 'primary_subtle' | 'negative_subtle' export type ButtonSize = 'tiny' | 'small' | 'large' -export type ButtonShape = 'round' | 'square' | 'default' +export type ButtonShape = 'round' | 'square' | 'rectangular' | 'default' export type VariantProps = { /** * The style variation of the button @@ -56,6 +56,11 @@ export type VariantProps = { size?: ButtonSize /** * The shape of the button + * + * - `default`: Pill shaped. Most buttons should use this shape. + * - `round`: Circular. For icon-only buttons. + * - `square`: Square. For icon-only buttons. + * - `rectangular`: Rectangular. Matches previous style, use when adjacent to form fields. */ shape?: ButtonShape } @@ -453,6 +458,29 @@ export const Button = React.forwardRef( gap: 2, }) } + } else if (shape === 'rectangular') { + if (size === 'large') { + baseStyles.push({ + paddingVertical: 12, + paddingHorizontal: 25, + borderRadius: 10, + gap: 3, + }) + } else if (size === 'small') { + baseStyles.push({ + paddingVertical: 8, + paddingHorizontal: 13, + borderRadius: 8, + gap: 3, + }) + } else if (size === 'tiny') { + baseStyles.push({ + paddingVertical: 5, + paddingHorizontal: 9, + borderRadius: 6, + gap: 2, + }) + } } else if (shape === 'round' || shape === 'square') { /* * These sizes match the actual rendered size on screen, based on diff --git a/src/components/Select/index.tsx b/src/components/Select/index.tsx index 33a828911e..a723e52370 100644 --- a/src/components/Select/index.tsx +++ b/src/components/Select/index.tsx @@ -106,7 +106,7 @@ export function Trigger({children, label}: TriggerProps) { style={[a.flex_1, a.justify_between]} color="secondary" size="small" - variant="solid"> + shape="rectangular"> <>{children} ) diff --git a/src/screens/Search/Shell.tsx b/src/screens/Search/Shell.tsx index 7cf7e77936..f3f333f080 100644 --- a/src/screens/Search/Shell.tsx +++ b/src/screens/Search/Shell.tsx @@ -362,7 +362,8 @@ export function SearchScreenShell({ size="large" variant="ghost" color="secondary" - style={[a.px_sm, a.rounded_sm]} + shape="rectangular" + style={[a.px_sm]} onPress={onPressCancelSearch} hitSlop={HITSLOP_10}> diff --git a/src/screens/Settings/AppPasswords.tsx b/src/screens/Settings/AppPasswords.tsx index 9bacf67cb3..2146150542 100644 --- a/src/screens/Settings/AppPasswords.tsx +++ b/src/screens/Settings/AppPasswords.tsx @@ -5,7 +5,6 @@ import Animated, { FadeOut, LayoutAnimationConfig, LinearTransition, - StretchOutY, } from 'react-native-reanimated' import {type ComAtprotoServerListAppPasswords} from '@atproto/api' import {msg, Trans} from '@lingui/macro' @@ -14,7 +13,6 @@ import {type NativeStackScreenProps} from '@react-navigation/native-stack' import {type CommonNavigatorParams} from '#/lib/routes/types' import {cleanError} from '#/lib/strings/errors' -import {isWeb} from '#/platform/detection' import { useAppPasswordDeleteMutation, useAppPasswordsQuery, @@ -94,7 +92,7 @@ export function AppPasswordsScreen({}: Props) { key={appPassword.name} style={a.w_full} entering={FadeIn} - exiting={isWeb ? FadeOut : StretchOutY} + exiting={FadeOut} layout={LinearTransition.delay(150)}> @@ -188,6 +186,7 @@ function AppPasswordCard({ variant="ghost" color="negative" size="small" + shape="square" style={[a.bg_transparent]} onPress={() => deleteControl.open()}> diff --git a/src/screens/Settings/LanguageSettings.tsx b/src/screens/Settings/LanguageSettings.tsx index d035e65926..ad767872ce 100644 --- a/src/screens/Settings/LanguageSettings.tsx +++ b/src/screens/Settings/LanguageSettings.tsx @@ -164,7 +164,7 @@ export function LanguageSettingsScreen({}: Props) { label={_(msg`Select content languages`)} size="small" color="secondary" - variant="solid" + shape="rectangular" onPress={onPressContentLanguages} style={[a.justify_start, web({maxWidth: 400})]}> void}) { value={currentAccount?.did ?? ''} label={_(msg`Copy DID`)} size="large" - variant="solid" + shape="rectangular" color="secondary" - style={[a.px_md, a.border, t.atoms.border_contrast_low]}> + style={[ + a.px_md, + a.border, + t.atoms.border_contrast_low, + t.atoms.bg_contrast_25, + ]}> {currentAccount?.did}