Skip to content

Commit eba2ea9

Browse files
fix: Sidebar fallback avatar logic (#487)
* fix: sidebar fallback avatar logic * feat: update sidebar docs regarding leadingIcon * feat: update sidebar avatar color
1 parent 333d756 commit eba2ea9

File tree

4 files changed

+30
-15
lines changed

4 files changed

+30
-15
lines changed

apps/www/src/app/examples/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,13 @@ const Page = () => {
8686
</Sidebar.Header>
8787

8888
<Sidebar.Main>
89-
<Sidebar.Item href='#' active>
89+
<Sidebar.Item href='#' active leadingIcon={<BellIcon />}>
9090
Dashboard
9191
</Sidebar.Item>
9292

93-
<Sidebar.Item href='#'>Analytics</Sidebar.Item>
93+
<Sidebar.Item href='#' leadingIcon={0}>
94+
Analytics
95+
</Sidebar.Item>
9496

9597
<Sidebar.Group label='Resources' leadingIcon={<FilterIcon />}>
9698
<Sidebar.Item href='#'>Reports</Sidebar.Item>

apps/www/src/content/docs/components/sidebar/index.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ The header section is a container component that accepts all `div` props. It's c
6464

6565
### Sidebar.Item Props
6666

67+
*Note: `leadingIcon` is optional and will show a fallback avatar only in collapsed state. You can pass `<></>` to render truly nothing.*
68+
6769
<auto-type-table path="./props.ts" name="SidebarItemProps" />
6870

6971
## Examples

apps/www/src/content/docs/components/sidebar/props.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ export interface SidebarGroupProps {
3535
}
3636

3737
export interface SidebarItemProps {
38-
/** ReactNode for the item's icon. */
38+
/**
39+
* ReactNode for the item's icon.
40+
*
41+
* If not provided, the component will show a fallback avatar only in collapsed state.
42+
*/
3943
leadingIcon?: ReactNode;
4044

4145
/** String for the link destination. */

packages/raystack/components/sidebar/sidebar.tsx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
forwardRef,
1111
useContext
1212
} from 'react';
13-
import { Avatar, getAvatarColor } from '../avatar';
13+
import { Avatar } from '../avatar';
1414
import { Flex } from '../flex';
1515
import { Tooltip } from '../tooltip';
1616
import styles from './sidebar.module.css';
@@ -178,7 +178,13 @@ const SidebarItem = forwardRef<HTMLAnchorElement, SidebarItemProps>(
178178
ref
179179
) => {
180180
const { isCollapsed, hideCollapsedItemTooltip } =
181-
useContext(SidebarContext); // To prevent prop drillng
181+
useContext(SidebarContext);
182+
183+
const shouldShowFallback =
184+
leadingIcon == undefined &&
185+
isCollapsed &&
186+
typeof children === 'string' &&
187+
children.length > 0;
182188

183189
const content = cloneElement(
184190
as,
@@ -199,16 +205,17 @@ const SidebarItem = forwardRef<HTMLAnchorElement, SidebarItemProps>(
199205
className={cx(styles['nav-leading-icon'], classNames?.leadingIcon)}
200206
aria-hidden='true'
201207
>
202-
{leadingIcon ||
203-
(typeof children === 'string' && children.length > 0 ? (
204-
<Avatar
205-
size={1}
206-
variant='soft'
207-
color={getAvatarColor(children)}
208-
fallback={children[0].toUpperCase()}
209-
style={{ cursor: 'pointer' }}
210-
/>
211-
) : null)}
208+
{shouldShowFallback ? (
209+
<Avatar
210+
size={1}
211+
variant='soft'
212+
color='neutral'
213+
fallback={children[0].toUpperCase()}
214+
style={{ cursor: 'pointer' }}
215+
/>
216+
) : (
217+
leadingIcon
218+
)}
212219
</Flex>
213220
{!isCollapsed && <span className={styles['nav-text']}>{children}</span>}
214221
</>

0 commit comments

Comments
 (0)