diff options
| author | Oliver <oliver@mohlin.dev> | 2025-09-03 14:40:21 +0200 |
|---|---|---|
| committer | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-09-22 12:35:43 +0200 |
| commit | e98c3de9715a56901120453c188ec04476714292 (patch) | |
| tree | 86c634ec9967e807a99aff2c1d5f3a37d34d66fd | |
| parent | 6f030ac691e6ea9710a4f58ac722fc51ff564cc2 (diff) | |
| download | mullvadvpn-e98c3de9715a56901120453c188ec04476714292.tar.xz mullvadvpn-e98c3de9715a56901120453c188ec04476714292.zip | |
Use ListItem components in Accordion
11 files changed, 46 insertions, 126 deletions
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/default-listbox-option/DefaultListboxOption.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/default-listbox-option/DefaultListboxOption.tsx index faf7f552bd..ceb78299f0 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/default-listbox-option/DefaultListboxOption.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/default-listbox-option/DefaultListboxOption.tsx @@ -1,9 +1,7 @@ import { ListboxOptionProps } from '../../lib/components/listbox/components'; -import { ListboxOptionTriggerProps } from '../../lib/components/listbox/components/listbox-option/components'; import { Listbox } from '../../lib/components/listbox/Listbox'; -export type DefaultListboxOptionProps<T> = ListboxOptionProps<T> & - Omit<ListboxOptionTriggerProps, keyof ListboxOptionProps<T>>; +export type DefaultListboxOptionProps<T> = ListboxOptionProps<T>; export function DefaultListboxOption<T>({ value, @@ -13,8 +11,8 @@ export function DefaultListboxOption<T>({ ...props }: DefaultListboxOptionProps<T>) { return ( - <Listbox.Option level={1} value={value} animation={animation} disabled={disabled}> - <Listbox.Option.Trigger {...props}> + <Listbox.Option level={1} value={value} animation={animation} disabled={disabled} {...props}> + <Listbox.Option.Trigger> <Listbox.Option.Item> <Listbox.Option.Content> <Listbox.Option.Group> diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/Accordion.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/Accordion.tsx index 25a8fd14cd..b2da681d10 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/Accordion.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/Accordion.tsx @@ -1,12 +1,14 @@ import React from 'react'; -import styled from 'styled-components'; -import { FlexColumn } from '../flex-column'; +import { ListItem, ListItemProps } from '../list-item'; import { AccordionProvider } from './AccordionContext'; -import { AccordionHeader, AccordionTrigger } from './components'; -import { AccordionContent } from './components/AccordionContent'; -import { AccordionIcon } from './components/AccordionIcon'; -import { AccordionTitle } from './components/AccordionTitle'; +import { + AccordionContent, + AccordionHeader, + AccordionIcon, + AccordionTitle, + AccordionTrigger, +} from './components'; export type AccordionAnimation = 'flash' | 'dim'; @@ -16,11 +18,7 @@ export type AccordionProps = { disabled?: boolean; animation?: AccordionAnimation; children?: React.ReactNode; -} & React.ComponentPropsWithRef<'div'>; - -const StyledAccordion = styled(FlexColumn)` - width: 100%; -`; +} & ListItemProps; function Accordion({ expanded = false, @@ -40,11 +38,10 @@ function Accordion({ titleId={titleId} expanded={expanded} onExpandedChange={onOpenChange} - disabled={disabled} - animation={animation}> - <StyledAccordion $flex={1} {...props}> + disabled={disabled}> + <ListItem disabled={disabled} animation={animation} {...props}> {children} - </StyledAccordion> + </ListItem> </AccordionProvider> ); } diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionHeader.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionHeader.tsx index ce28143976..eee672f61b 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionHeader.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionHeader.tsx @@ -2,8 +2,7 @@ import styled, { css, RuleSet } from 'styled-components'; import { colors } from '../../../foundations'; import { Flex } from '../../flex'; -import { useAccordionContext } from '../AccordionContext'; -import { useAnimation } from '../hooks'; +import { ListItem } from '../../list-item'; export type AccordionHeaderProps = { children?: React.ReactNode; @@ -28,16 +27,9 @@ export const StyledAccordionHeader = styled(Flex)<{ `; export function AccordionHeader({ children }: AccordionHeaderProps) { - const animation = useAnimation(); - const { disabled } = useAccordionContext(); return ( - <StyledAccordionHeader - $padding={{ horizontal: 'medium', vertical: 'small' }} - $alignItems="center" - $justifyContent="space-between" - $animation={animation} - $disabled={disabled}> - {children} - </StyledAccordionHeader> + <ListItem.Item> + <ListItem.Content>{children}</ListItem.Content> + </ListItem.Item> ); } diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionIcon.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionIcon.tsx index 043a72fa00..33b3936978 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionIcon.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionIcon.tsx @@ -1,18 +1,13 @@ -import styled from 'styled-components'; - -import { Icon, IconProps } from '../../icon'; +import { IconProps } from '../../icon'; +import { ListItem } from '../../list-item'; import { useAccordionContext } from '../AccordionContext'; export type AccordionIconProps = Omit<IconProps, 'icon'> & { icon?: IconProps['icon']; }; -export const StyledAccordionIcon = styled(Icon)` - flex-shrink: 0; -`; - -export function AccordionIcon({ icon, color = 'whiteAlpha80', ...props }: AccordionIconProps) { - const { expanded: open } = useAccordionContext(); - const iconName = icon || (open ? 'chevron-up' : 'chevron-down'); - return <StyledAccordionIcon icon={iconName} color={color} {...props} />; +export function AccordionIcon({ icon, ...props }: AccordionIconProps) { + const { expanded } = useAccordionContext(); + const iconName = icon || (expanded ? 'chevron-up' : 'chevron-down'); + return <ListItem.Icon icon={iconName} {...props} />; } diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionTitle.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionTitle.tsx index e1329dbf77..fab41c638c 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionTitle.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionTitle.tsx @@ -1,23 +1,10 @@ -import styled from 'styled-components'; - -import { Text } from '../../typography'; +import { ListItem } from '../../list-item'; +import { TextProps } from '../../typography'; import { useAccordionContext } from '../AccordionContext'; -export type AccordionTitleProps = { - children?: React.ReactNode; -}; - -export const StyledTitleLabel = styled(Text)``; +export type AccordionTitleProps = TextProps; export function AccordionTitle({ children }: AccordionTitleProps) { - const { titleId, disabled } = useAccordionContext(); - return ( - <StyledTitleLabel - id={titleId} - $padding="medium" - color={disabled ? 'whiteAlpha60' : 'white'} - variant="titleMedium"> - {children} - </StyledTitleLabel> - ); + const { titleId } = useAccordionContext(); + return <ListItem.Label id={titleId}>{children}</ListItem.Label>; } diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionTrigger.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionTrigger.tsx index dfaffdf317..dbf1016d90 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionTrigger.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/AccordionTrigger.tsx @@ -1,35 +1,12 @@ import React from 'react'; -import styled from 'styled-components'; -import { colors } from '../../../foundations'; +import { ListItem } from '../../list-item'; import { useAccordionContext } from '../AccordionContext'; -import { StyledAccordionHeader } from './AccordionHeader'; -import { StyledAccordionIcon } from './AccordionIcon'; export type AccordionTriggerProps = { children?: React.ReactNode; } & React.ButtonHTMLAttributes<HTMLButtonElement>; -const StyledAccordionTrigger = styled.button` - background-color: transparent; - &&:hover > ${StyledAccordionHeader} { - background-color: ${colors.blue60}; - } - &&:hover > ${StyledAccordionIcon} { - background-color: ${colors.whiteAlpha60}; - } - &&:active > ${StyledAccordionHeader} { - background-color: ${colors.blue40}; - } - &&:active > ${StyledAccordionIcon} { - background-color: ${colors.whiteAlpha40}; - } - &&:focus-visible { - outline: 2px solid ${colors.white}; - outline-offset: -2px; - } -`; - export function AccordionTrigger({ children }: AccordionTriggerProps) { const { contentId, triggerId, titleId, expanded, onExpandedChange } = useAccordionContext(); @@ -42,13 +19,13 @@ export function AccordionTrigger({ children }: AccordionTriggerProps) { ); return ( - <StyledAccordionTrigger + <ListItem.Trigger id={triggerId} aria-labelledby={titleId} aria-controls={contentId} aria-expanded={expanded ? 'true' : 'false'} onClick={onClick}> {children} - </StyledAccordionTrigger> + </ListItem.Trigger> ); } diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/index.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/index.ts index abd6b8865b..7727d016fa 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/index.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/components/index.ts @@ -1,2 +1,5 @@ +export * from './AccordionContent'; export * from './AccordionHeader'; export * from './AccordionTrigger'; +export * from './AccordionTitle'; +export * from './AccordionIcon'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/hooks/index.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/hooks/index.ts deleted file mode 100644 index 64aafcab29..0000000000 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/hooks/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './useAnimation'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/hooks/useAnimation.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/hooks/useAnimation.tsx deleted file mode 100644 index be34d7963b..0000000000 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/accordion/hooks/useAnimation.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { css, keyframes } from 'styled-components'; - -import { colors } from '../../../foundations'; -import { useAccordionContext } from '../AccordionContext'; - -const flash = keyframes` - 0% { background-color: var(--background-color) } - 50% { background-color: ${colors.whiteOnBlue20} } - 100% { background-color: var(--background-color) } -`; - -const dim = keyframes` - 0% { opacity: 100% } - 25% { opacity: 50% } - 50% { opacity: 50% } - 75% { opacity: 50% } - 100% { opacity: 100% } -`; - -export const useAnimation = () => { - const { animation } = useAccordionContext(); - if (animation === 'flash') { - return css` - animation: ${flash} 0.75s ease-in-out 0s 2 normal forwards; - `; - } - if (animation === 'dim') { - return css` - animation: ${dim} 1.5s ease-in-out 0s 1 normal forwards; - `; - } - return undefined; -}; diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/list-item/ListItem.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/list-item/ListItem.tsx index 7b234e1a62..344dc67d64 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/list-item/ListItem.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/list-item/ListItem.tsx @@ -21,12 +21,12 @@ export type ListItemProps = { disabled?: boolean; animation?: ListItemAnimation; children: React.ReactNode; -}; +} & React.ComponentPropsWithRef<'div'>; -const ListItem = ({ level = 0, disabled, animation, children }: ListItemProps) => { +const ListItem = ({ level = 0, disabled, animation, children, ...props }: ListItemProps) => { return ( <ListItemProvider level={level} disabled={disabled} animation={animation}> - {children} + <div {...props}>{children}</div> </ListItemProvider> ); }; diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/listbox/components/listbox-option/components/listbox-option-trigger/ListboxOptionTrigger.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/listbox/components/listbox-option/components/listbox-option-trigger/ListboxOptionTrigger.tsx index 26c4371ede..c1f9e1d9c7 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/listbox/components/listbox-option/components/listbox-option-trigger/ListboxOptionTrigger.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/listbox/components/listbox-option/components/listbox-option-trigger/ListboxOptionTrigger.tsx @@ -36,12 +36,17 @@ export const StyledListItemOptionTrigger = styled.li<{ $disabled?: boolean }>` } &&[aria-selected='true'] { - &:hover { + ${StyledListItemOptionItem} { + ${StyledListItemOptionItem} { + background-color: ${colors.green}; + } + } + &&:hover { ${StyledListItemOptionItem} { background-color: ${colors.green}; } } - &:active { + &&:active { ${StyledListItemOptionItem} { background-color: ${colors.green}; } |
