Skip to content

Commit

Permalink
feat: Add tab label icons
Browse files Browse the repository at this point in the history
  • Loading branch information
flozia committed Nov 21, 2024
1 parent 62f4b9f commit 5ec7db7
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
h2 {
font: $text-title-xs;
}

& [role="tab"]::after {
width: calc(100% - 24px - $spacing-xs);
}
}

.content {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,40 @@ import { TabType } from "../dashboard/View";
import { TabList } from "../../../../../../components/client/TabList";
import styles from "./SettingsContent.module.scss";
import { SettingsPanel } from "./panels";
import {
EmailOutlineIcon,
MailboxOutlineIcon,
ContactsOutlineIcon,
} from "../../../../../../components/server/Icons";

function SettingsContent() {
const l10n = useL10n();
const tabsData = [
{
name: l10n.getString("settings-tab-label-edit-info"),
name: (
<>
<EmailOutlineIcon alt="" width={24} height={24} />
{l10n.getString("settings-tab-label-edit-info")}
</>
),
key: "edit-info",
},
{
name: l10n.getString("settings-tab-label-notifications"),
name: (
<>
<MailboxOutlineIcon alt="" width={24} height={24} />
{l10n.getString("settings-tab-label-notifications")}
</>
),
key: "label-notification",
},
{
name: l10n.getString("settings-tab-label-manage-account"),
name: (
<>
<ContactsOutlineIcon alt="" width={24} height={24} />
{l10n.getString("settings-tab-label-manage-account")}
</>
),
key: "manage-account",
},
];
Expand All @@ -42,6 +62,7 @@ function SettingsContent() {
onSelectionChange={(selectedKey) => {
setActiveTab(selectedKey as TabType);
}}
variant="secondary"
/>
</header>
<div className={styles.content}>
Expand Down
28 changes: 25 additions & 3 deletions src/app/components/client/TabList.module.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
@import "../../tokens";

.container {
display: flex;
}

.tabs {
display: flex;
gap: $spacing-sm;
Expand All @@ -11,15 +15,17 @@

.tab {
cursor: pointer;
display: flex;
gap: $spacing-xs;
padding: $spacing-sm;
position: relative;

&::after {
bottom: 0;
content: "";
height: $border-focus-width;
left: 0;
position: absolute;
right: 0;
width: 100%;
}

Expand All @@ -30,6 +36,22 @@
}
}

.container {
display: flex;
.secondary {
.tabs {
align-items: flex-start;
gap: $spacing-sm;
}

.tab {
color: $color-grey-40;
padding: $spacing-xs 0;

&[aria-selected="true"] {
color: $color-purple-50;
&::after {
background: $color-purple-50;
height: 2px;
}
}
}
}
14 changes: 10 additions & 4 deletions src/app/components/client/TabList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ import { Item, useTabListState } from "react-stately";
import styles from "./TabList.module.scss";
import { TabListState, TabListStateOptions } from "@react-stately/tabs";

export type TabsProps =
export type TabsProps = (
| TabListStateOptions<object>
| AriaTabListOptions<object>;
| AriaTabListOptions<object>
) & {
variant?: "primary" | "secondary";
};

export type TabListProps = TabsProps & {
tabs: Array<{
key: Key;
name: string;
name: string | ReactNode;
content?: ReactNode;
}>;
};
Expand Down Expand Up @@ -52,7 +55,10 @@ function Tabs(props: TabsProps) {
const { collection, selectedItem } = state;

return (
<div className={styles.container} data-test="test">
<div
className={`${styles.container} ${props.variant ? styles[props.variant] : ""}`}
data-test="test"
>
<div {...tabListProps} ref={ref} className={styles.tabs}>
{[...collection].map((item) => (
<Tab key={item.key} item={item} state={state} />
Expand Down
136 changes: 136 additions & 0 deletions src/app/components/server/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,142 @@ export const EmailIcon = ({
);
};

// Keywords: email, envelope, outline
// Link to icon: https://www.figma.com/design/eLH4KiHC3FxEPwr6uNMnE9/Pixel-Perfect-Icon-Set-%E2%80%93%C2%A0Source?node-id=106-10937&m=dev
export const EmailOutlineIcon = ({
alt,
...props
}: SVGProps<SVGSVGElement> & { alt: string }) => {
return (
<svg
role="img"
aria-label={alt}
aria-hidden={alt === ""}
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}
className={`${props.className ?? ""} ${styles.colorifyStroke}`}
fill="transparent"
>
<title>{alt}</title>
<path
d="M16 5H18C19.7 5 21 6.3 21 8V16C21 17.7 19.7 19 18 19H6C4.3 19 3 17.7 3 16V8C3 6.3 4.3 5 6 5H8H16Z"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M20.8996 7.19995L14.2996 13L11.9996 15L9.69961 13L3.09961 7.19995"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M9.70039 13L3.90039 18.2"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M20.0998 18.2L14.2998 13"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
};

// Keywords: mailbox, inbox
// Link to icon: https://www.figma.com/design/eLH4KiHC3FxEPwr6uNMnE9/Pixel-Perfect-Icon-Set-%E2%80%93%C2%A0Source?node-id=106-11247&t=rzqMRa2ZGRqbRo11-4
export const MailboxOutlineIcon = ({
alt,
...props
}: SVGProps<SVGSVGElement> & { alt: string }) => {
return (
<svg
role="img"
aria-label={alt}
aria-hidden={alt === ""}
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}
className={`${props.className ?? ""} ${styles.colorifyStroke}`}
fill="transparent"
>
<title>{alt}</title>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M11 10V17H3V10C3 7.8 4.8 6 7 6C9.2 6 11 7.8 11 10Z"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M21 10V17H3V10C3 7.8 4.8 6 7 6H17C19.2 6 21 7.8 21 10Z"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M16 17L16 21"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M19 3H18C16.8954 3 16 3.89543 16 5V11"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
};

// Keywords: contact, person, info
// Link to icon: https://www.figma.com/design/eLH4KiHC3FxEPwr6uNMnE9/Pixel-Perfect-Icon-Set-%E2%80%93%C2%A0Source?node-id=106-16231&t=yP5KZQSgof8HbkkD-4
export const ContactsOutlineIcon = ({
alt,
...props
}: SVGProps<SVGSVGElement> & { alt: string }) => {
return (
<svg
role="img"
aria-label={alt}
aria-hidden={alt === ""}
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
{...props}
className={`${props.className ?? ""} ${styles.colorifyStroke}`}
fill="transparent"
>
<title>{alt}</title>
<path
d="M3 17V7C3 4.8 4.8 3 7 3H17C19.2 3 21 4.8 21 7V17C21 19.2 19.2 21 17 21H7C4.8 21 3 19.2 3 17Z"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M12 11.7C13.3 11.7 14.3 10.7 14.3 9.4C14.3 8.1 13.3 7 12 7C10.7 7 9.69995 8 9.69995 9.3C9.69995 10.6 10.7 11.7 12 11.7Z"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M6.6001 21V20.2C6.6001 18.7 7.2001 17.3 8.2001 16.3C9.2001 15.3 10.5001 14.7 12.1001 14.7C15.1001 14.7 17.5001 17.1 17.5001 20.1V21"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
};

export const LocationPinIcon = ({
alt,
...props
Expand Down

0 comments on commit 5ec7db7

Please sign in to comment.