Private
Public Access
1
0

feat: Fluent UI Outlook Lite + connections mockup

This commit is contained in:
2026-04-14 18:52:25 +00:00
parent 1199eff6c3
commit dfa4010406
34820 changed files with 1003813 additions and 205 deletions

View File

@@ -0,0 +1,154 @@
'use client';
import { iconFilledClassName, iconRegularClassName } from '@fluentui/react-icons';
import { tokens, typographyStyles } from '@fluentui/react-theme';
import { makeResetStyles, makeStyles } from '@griffel/react';
// Styles shared by several nav components.
export const navItemTokens = {
defaultDrawerWidth: 260,
indicatorOffset: 16,
indicatorWidth: 4,
indicatorHeight: 20,
backgroundColor: tokens.colorNeutralBackground4,
backgroundColorHover: tokens.colorNeutralBackground4Hover,
backgroundColorPressed: tokens.colorNeutralBackground4Pressed,
animationTokens: {
animationDuration: tokens.durationFaster,
animationFillMode: 'both',
animationTimingFunction: tokens.curveLinear
},
transitionTokens: {
transitionDuration: tokens.durationFaster,
transitionTimingFunction: tokens.curveLinear,
transitionProperty: 'background'
}
};
/**
* Styles for the root slot
* Shared across NavItem, NavCategoryItem, NavSubItem, and AppItem
*/ export const useRootDefaultClassName = makeResetStyles({
display: 'flex',
textTransform: 'none',
position: 'relative',
justifyContent: 'start',
alignItems: 'flex-start',
textAlign: 'left',
gap: tokens.spacingVerticalL,
padding: `${tokens.spacingVerticalMNudge} ${tokens.spacingHorizontalS} ${tokens.spacingVerticalMNudge} ${tokens.spacingHorizontalMNudge}`,
backgroundColor: navItemTokens.backgroundColor,
borderRadius: tokens.borderRadiusMedium,
color: tokens.colorNeutralForeground2,
textDecorationLine: 'none',
border: 'none',
// this element can change between a button and an anchor
// so we need to reset box sizing to prevent horizontal overflow
boxSizing: 'border-box',
cursor: 'pointer',
transitionDuration: navItemTokens.animationTokens.animationDuration,
transitionTimingFunction: navItemTokens.animationTokens.animationTimingFunction,
transitionProperty: 'background',
width: '100%',
...typographyStyles.body1,
':hover': {
backgroundColor: navItemTokens.backgroundColorHover
},
// Use custom insert focus indicator
'&:focus-visible': {
outline: `${tokens.strokeWidthThick} solid ${tokens.colorStrokeFocus2}`,
outlineOffset: `calc(${tokens.strokeWidthThick} * -1)`
}
});
export const useSmallStyles = makeStyles({
root: {
padding: `${tokens.spacingVerticalXS} ${tokens.spacingHorizontalS} ${tokens.spacingVerticalXS} ${tokens.spacingHorizontalMNudge}`
}
});
/**
* Styles for the content slot (children)
* Shared across NavItem, NavCategoryItem, NavSubItem, and AppItem
*/ export const useContentStyles = makeStyles({
selected: typographyStyles.body1Strong
});
/**
* French fry styles
* Shared across NavItem, NavCategoryItem, and NavSubItem
*/ export const useIndicatorStyles = makeStyles({
base: {
'::after': {
position: 'absolute',
...navItemTokens.animationTokens,
animationName: {
'0%': {
background: 'transparent'
},
'100%': {
background: tokens.colorCompoundBrandForeground1
}
},
marginInlineStart: `-${navItemTokens.indicatorOffset}px`,
backgroundColor: tokens.colorCompoundBrandForeground1,
height: `${navItemTokens.indicatorHeight}px`,
width: `${navItemTokens.indicatorWidth}px`,
borderRadius: tokens.borderRadiusCircular,
content: '""'
},
'@media (forced-colors: active)': {
'::after': {
outline: `solid 2px ${tokens.colorTransparentStroke}`,
outlineOffset: '-2px'
}
}
}
});
/**
* Styles for the icon slot
* Shared across NavItem, NavCategoryItem, and NavSubItem
* We use the grid trick to stack the filled and regular icons on top of each other
*/ export const useIconStyles = makeStyles({
base: {
display: 'grid',
gridTemplateAreas: 'overlay-area',
minHeight: '20px',
minWidth: '20px',
alignItems: 'top',
justifyContent: 'center',
overflow: 'hidden',
[`& .${iconFilledClassName}`]: {
gridArea: 'overlay-area',
color: 'transparent',
display: 'none'
},
[`& .${iconRegularClassName}`]: {
gridArea: 'overlay-area',
display: 'inline'
}
},
selected: {
[`& .${iconFilledClassName}`]: {
...navItemTokens.animationTokens,
display: 'inline',
animationName: {
'0%': {
opacity: 0,
color: 'transparent'
},
'100%': {
opacity: 1,
color: tokens.colorNeutralForeground2BrandSelected
}
}
},
[`& .${iconRegularClassName}`]: {
...navItemTokens.animationTokens,
animationName: {
'0%': {
opacity: 1,
color: tokens.colorNeutralForeground2
},
'100%': {
opacity: 0,
color: 'transparent'
}
}
}
}
});