feat: add Settings/Accounts Settings section (#2853)

Closes #2818
This commit is contained in:
Thaïs
2023-12-07 12:43:38 +01:00
committed by GitHub
parent a8ecc23cbe
commit 62fa55eae6
11 changed files with 172 additions and 15 deletions

View File

@ -0,0 +1,43 @@
import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
import { SettingsNavigationCard } from '@/settings/components/SettingsNavigationCard';
import { IconCalendarEvent, IconMailCog } from '@/ui/display/icon';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { Section } from '@/ui/layout/section/components/Section';
const StyledCardsContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(4)};
margin-top: ${({ theme }) => theme.spacing(6)};
`;
export const SettingsAccountsSettingsSection = () => {
const navigate = useNavigate();
return (
<Section>
<H2Title
title="Settings"
description="Configure your emails and calendar settings."
/>
<StyledCardsContainer>
<SettingsNavigationCard
Icon={IconMailCog}
title="Emails"
onClick={() => navigate('/settings/accounts/emails')}
>
Set email visibility, manage your blocklist and more.
</SettingsNavigationCard>
<SettingsNavigationCard
Icon={IconCalendarEvent}
title="Calendar"
disabled
hasSoonPill
>
Configure and customize your calendar preferences.
</SettingsNavigationCard>
</StyledCardsContainer>
</Section>
);
};

View File

@ -0,0 +1,79 @@
import { ReactNode } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconChevronRight } from '@/ui/display/icon';
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { SoonPill } from '@/ui/display/pill/components/SoonPill';
import { Card } from '@/ui/layout/card/components/Card';
type SettingsNavigationCardProps = {
children: ReactNode;
disabled?: boolean;
hasSoonPill?: boolean;
Icon: IconComponent;
onClick?: () => void;
title: string;
};
const StyledCard = styled(Card)<{
disabled?: boolean;
onClick?: () => void;
}>`
color: ${({ theme }) => theme.font.color.tertiary};
cursor: ${({ disabled, onClick }) =>
disabled ? 'not-allowed' : onClick ? 'pointer' : 'default'};
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing(2)};
padding-bottom: ${({ theme }) => theme.spacing(4)};
padding-top: ${({ theme }) => theme.spacing(4)};
`;
const StyledHeader = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(3)};
`;
const StyledTitle = styled.div`
color: ${({ theme }) => theme.font.color.secondary};
display: flex;
flex: 1 0 auto;
font-weight: ${({ theme }) => theme.font.weight.medium};
gap: ${({ theme }) => theme.spacing(2)};
justify-content: flex-start;
`;
const StyledIconChevronRight = styled(IconChevronRight)`
color: ${({ theme }) => theme.font.color.light};
`;
const StyledDescription = styled.div`
padding-left: ${({ theme }) => theme.spacing(8)};
`;
export const SettingsNavigationCard = ({
children,
disabled,
hasSoonPill,
Icon,
onClick,
title,
}: SettingsNavigationCardProps) => {
const theme = useTheme();
return (
<StyledCard disabled={disabled} onClick={onClick}>
<StyledHeader>
<Icon size={theme.icon.size.lg} stroke={theme.icon.stroke.sm} />
<StyledTitle>
{title}
{hasSoonPill && <SoonPill />}
</StyledTitle>
<StyledIconChevronRight size={theme.icon.size.sm} />
</StyledHeader>
<StyledDescription>{children}</StyledDescription>
</StyledCard>
);
};

View File

@ -1,16 +1,16 @@
import { ReactNode } from 'react';
import styled from '@emotion/styled';
import { Card } from '@/ui/layout/card/components/Card';
type SettingsObjectFieldTypeCardProps = {
className?: string;
preview: ReactNode;
form?: ReactNode;
};
const StyledPreviewContainer = styled.div`
const StyledPreviewContainer = styled(Card)`
background-color: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
padding: ${({ theme }) => theme.spacing(4)};
&:not(:last-child) {
@ -32,14 +32,12 @@ const StyledPreviewContent = styled.div`
gap: 6px;
`;
const StyledFormContainer = styled.div`
background-color: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
const StyledFormContainer = styled(Card)`
border-top: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
overflow: hidden;
padding: 0;
`;
export const SettingsObjectFieldTypeCard = ({

View File

@ -37,6 +37,10 @@ const StyledIconCheck = styled(IconCheck)`
margin-left: auto;
`;
const StyledSoonPill = styled(SoonPill)`
margin-left: auto;
`;
type SettingsObjectTypeCardProps = {
prefixIcon?: React.ReactNode;
title: string;
@ -68,7 +72,7 @@ export const SettingsObjectTypeCard = ({
>
{prefixIcon}
<StyledTag color={color} text={title} />
{soon && <SoonPill />}
{soon && <StyledSoonPill />}
{!disabled && selected && <StyledIconCheck size={theme.icon.size.md} />}
</StyledObjectTypeCard>
);

View File

@ -6,6 +6,7 @@ import { Tag } from '@/ui/display/tag/components/Tag';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
import { useLazyLoadIcon } from '@/ui/input/hooks/useLazyLoadIcon';
import { Card } from '@/ui/layout/card/components/Card';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
@ -22,11 +23,8 @@ type SettingsAboutSectionProps = {
onEdit: () => void;
};
const StyledCard = styled.div`
const StyledCard = styled(Card)`
align-items: center;
background-color: ${({ theme }) => theme.background.secondary};
border: ${({ theme }) => `1px solid ${theme.border.color.medium}`};
border-radius: ${({ theme }) => theme.border.radius.sm};
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
padding: ${({ theme }) => theme.spacing(2)};

View File

@ -60,6 +60,7 @@ export {
IconList,
IconLogout,
IconMail,
IconMailCog,
IconMap,
IconMinus,
IconMoneybag,

View File

@ -1,5 +1,9 @@
import styled from '@emotion/styled';
type SoonPillProps = {
className?: string;
};
const StyledSoonPill = styled.span`
align-items: center;
background: ${({ theme }) => theme.background.transparent.light};
@ -13,8 +17,9 @@ const StyledSoonPill = styled.span`
height: ${({ theme }) => theme.spacing(4)};
justify-content: flex-end;
line-height: ${({ theme }) => theme.text.lineHeight.lg};
margin-left: auto;
padding: ${({ theme }) => `0 ${theme.spacing(2)}`};
`;
export const SoonPill = () => <StyledSoonPill>Soon</StyledSoonPill>;
export const SoonPill = ({ className }: SoonPillProps) => (
<StyledSoonPill className={className}>Soon</StyledSoonPill>
);

View File

@ -277,6 +277,10 @@ const StyledButton = styled.button<
}
`;
const StyledSoonPill = styled(SoonPill)`
margin-left: auto;
`;
export const Button = ({
className,
Icon,
@ -307,7 +311,7 @@ export const Button = ({
>
{Icon && <Icon size={theme.icon.size.sm} />}
{title}
{soon && <SoonPill />}
{soon && <StyledSoonPill />}
</StyledButton>
);
};

View File

@ -0,0 +1,10 @@
import styled from '@emotion/styled';
const StyledCard = styled.div`
background-color: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
padding: ${({ theme }) => theme.spacing(3)};
`;
export { StyledCard as Card };

View File

@ -0,0 +1,13 @@
import { Meta, StoryObj } from '@storybook/react';
import { Card } from '../Card';
const meta: Meta<typeof Card> = {
title: 'UI/Layout/Card/Card',
component: Card,
};
export default meta;
type Story = StoryObj<typeof Card>;
export const Default: Story = {};

View File

@ -1,3 +1,4 @@
import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/SettingsAccountsSettingsSection';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { IconSettings } from '@/ui/display/icon';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
@ -7,6 +8,7 @@ export const SettingsAccounts = () => (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer>
<Breadcrumb links={[{ children: 'Accounts' }]} />
<SettingsAccountsSettingsSection />
</SettingsPageContainer>
</SubMenuTopBarContainer>
);