Files
bsky-social-app/src/components/forms/Toggle/Panel.tsx
T
Samuel Newman b422765aed [Threadgate] Tweak threadgate buttons (#9173)
* tweak in-post threadgate button

* tweak composer threadgate button

* reduce date length slightly

* pressed styles

* make date length depend on breakpoint

* add chevron to label btn

* add tiny chevron, special-case button icon width

* [Threadgate] Add hint (#9350)

* get tooltip working on web

* add compatibility layer for working in iOS sheets

* add timeout to profile tooltip now that it appears instantly

* rm debug code

* Update ThreadgateBtn.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* remeasure when keyboard changes

---------

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* fix types

* [Threadgate] Refresh dialog (#9342)

* wip new ui

* update threadgate dialog with new designs

* restore nobody option

* relayout android sheet when ratio changes

* fix ratio changing case in bottom sheet

* timebox reached, use setTimeout

* update panel styles

* missing imports

* extract out Panel

* tweak layout animation

* fix icon color

* use same color mechamism for icon as text

* restore the header

* refreshed toggle styles (#9343)

* [Threadgate] Persist settings (#9341)

* add persist toggle to threadgate dialog

* move state back down

* sort out spacing

* wire up query

* @surfdude29 tweaks

* use tiny chevron in WhoCanReply

* wait for prefetch before opening

* move Panel into the Toggle namespace

* default -> pref

* use medium date length

* rm hover state from web selects, fix border radius

* fix key issue in Selects

---------

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>
2025-11-14 06:21:37 -08:00

121 lines
2.7 KiB
TypeScript

import {createContext, useContext} from 'react'
import {View, type ViewStyle} from 'react-native'
import {atoms as a, tokens, useTheme} from '#/alf'
import {type Props as SVGIconProps} from '#/components/icons/common'
import {Text} from '#/components/Typography'
const PanelContext = createContext<{active: boolean}>({active: false})
/**
* A nice container for Toggles. See the Threadgate dialog for an example.
*/
export function Panel({
children,
active = false,
adjacent,
}: {
children: React.ReactNode
active?: boolean
adjacent?: 'leading' | 'trailing' | 'both'
}) {
const t = useTheme()
const leading = adjacent === 'leading' || adjacent === 'both'
const trailing = adjacent === 'trailing' || adjacent === 'both'
const rounding = {
borderTopLeftRadius: leading
? tokens.borderRadius.xs
: tokens.borderRadius.md,
borderTopRightRadius: leading
? tokens.borderRadius.xs
: tokens.borderRadius.md,
borderBottomLeftRadius: trailing
? tokens.borderRadius.xs
: tokens.borderRadius.md,
borderBottomRightRadius: trailing
? tokens.borderRadius.xs
: tokens.borderRadius.md,
} satisfies ViewStyle
return (
<View
style={[
a.w_full,
a.flex_row,
a.align_center,
a.gap_sm,
a.px_md,
a.py_md,
{minHeight: tokens.space._2xl + tokens.space.md * 2},
rounding,
active
? {backgroundColor: t.palette.primary_50}
: t.atoms.bg_contrast_50,
]}>
<PanelContext value={{active}}>{children}</PanelContext>
</View>
)
}
export function PanelText({
children,
icon,
}: {
children: React.ReactNode
icon?: React.ComponentType<SVGIconProps>
}) {
const t = useTheme()
const ctx = useContext(PanelContext)
const text = (
<Text
style={[
a.text_md,
a.flex_1,
ctx.active
? [a.font_medium, t.atoms.text]
: [t.atoms.text_contrast_medium],
]}>
{children}
</Text>
)
if (icon) {
// eslint-disable-next-line bsky-internal/avoid-unwrapped-text
return (
<View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}>
<PanelIcon icon={icon} />
{text}
</View>
)
}
return text
}
export function PanelIcon({
icon: Icon,
}: {
icon: React.ComponentType<SVGIconProps>
}) {
const t = useTheme()
const ctx = useContext(PanelContext)
return (
<Icon
style={[
ctx.active ? t.atoms.text : t.atoms.text_contrast_medium,
a.flex_shrink_0,
]}
size="md"
/>
)
}
/**
* A group of panels. TODO: auto-leading/trailing
*/
export function PanelGroup({children}: {children: React.ReactNode}) {
return <View style={[a.w_full, a.gap_2xs]}>{children}</View>
}