style
This commit is contained in:
@@ -189,7 +189,6 @@ const Sidebar = ({
|
|||||||
onSelectTenant,
|
onSelectTenant,
|
||||||
onOpenSettings,
|
onOpenSettings,
|
||||||
onUploadFiles,
|
onUploadFiles,
|
||||||
loading = false,
|
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
setCollapsed,
|
setCollapsed,
|
||||||
@@ -318,6 +317,50 @@ const Sidebar = ({
|
|||||||
cycleThemeMode();
|
cycleThemeMode();
|
||||||
}, [cycleThemeMode]);
|
}, [cycleThemeMode]);
|
||||||
|
|
||||||
|
const themeMenuSection =
|
||||||
|
typeof neutralHue === 'number' || typeof neutralHue === 'string'
|
||||||
|
? (
|
||||||
|
<div className="menu__section">
|
||||||
|
<div className="menu__heading menu__heading--with-actions">
|
||||||
|
<span>Theme</span>
|
||||||
|
<div className="menu__heading-actions">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="icon-button"
|
||||||
|
onClick={handleThemeModeToggle}
|
||||||
|
aria-label={`Switch theme (next: ${nextThemeLabel})`}
|
||||||
|
title={`Theme: ${themeModeLabel} (next: ${nextThemeLabel})`}
|
||||||
|
>
|
||||||
|
{themeModeIcon}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="icon-button"
|
||||||
|
onClick={handleNeutralHueReset}
|
||||||
|
aria-label="Reset neutral hue"
|
||||||
|
title="Reset neutral hue"
|
||||||
|
>
|
||||||
|
<RestoreIcon size={16} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label className="menu__slider" htmlFor={neutralHueInputId}>
|
||||||
|
<span className="menu__slider-label">Hue</span>
|
||||||
|
<input
|
||||||
|
id={neutralHueInputId}
|
||||||
|
type="range"
|
||||||
|
min="0"
|
||||||
|
max="360"
|
||||||
|
step="1"
|
||||||
|
value={neutralHue}
|
||||||
|
onChange={(event) => handleNeutralHueChange(event.target.value)}
|
||||||
|
/>
|
||||||
|
<span className="menu__slider-value">{neutralHue}°</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
const handleSearchInputChange = useCallback(
|
const handleSearchInputChange = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
onSearchChange?.(event.target.value);
|
onSearchChange?.(event.target.value);
|
||||||
@@ -348,6 +391,7 @@ const Sidebar = ({
|
|||||||
offset: 6,
|
offset: 6,
|
||||||
});
|
});
|
||||||
const showTenantList = tenants.length > 1;
|
const showTenantList = tenants.length > 1;
|
||||||
|
const menuClassName = `menu${!showTenantList && !themeMenuSection ? ' menu--simple' : ''}`;
|
||||||
|
|
||||||
const toggleTenantMenu = useCallback(() => {
|
const toggleTenantMenu = useCallback(() => {
|
||||||
if (!tenantMenuOpen && tenants.length === 0 && onSelectTenant) {
|
if (!tenantMenuOpen && tenants.length === 0 && onSelectTenant) {
|
||||||
@@ -426,50 +470,6 @@ const Sidebar = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const rootNode = folderNodes.get('root');
|
const rootNode = folderNodes.get('root');
|
||||||
const themeControls =
|
|
||||||
typeof neutralHue === 'number' || typeof neutralHue === 'string'
|
|
||||||
? (
|
|
||||||
<div className="sidebar-section sidebar-theme">
|
|
||||||
<div className="sidebar-section__header">
|
|
||||||
<h3>Theme</h3>
|
|
||||||
<div className="sidebar-section__actions">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="icon-button"
|
|
||||||
onClick={handleThemeModeToggle}
|
|
||||||
aria-label={`Switch theme (next: ${nextThemeLabel})`}
|
|
||||||
title={`Theme: ${themeModeLabel} (next: ${nextThemeLabel})`}
|
|
||||||
>
|
|
||||||
{themeModeIcon}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="icon-button"
|
|
||||||
onClick={handleNeutralHueReset}
|
|
||||||
aria-label="Reset neutral hue"
|
|
||||||
title="Reset neutral hue"
|
|
||||||
>
|
|
||||||
<RestoreIcon size={16} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<label className="sidebar-slider" htmlFor={neutralHueInputId}>
|
|
||||||
<span className="sidebar-slider__label">Hue</span>
|
|
||||||
<input
|
|
||||||
id={neutralHueInputId}
|
|
||||||
type="range"
|
|
||||||
min="0"
|
|
||||||
max="360"
|
|
||||||
step="1"
|
|
||||||
value={neutralHue}
|
|
||||||
onChange={(event) => handleNeutralHueChange(event.target.value)}
|
|
||||||
/>
|
|
||||||
<span className="sidebar-slider__value">{neutralHue}°</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className="sidebar">
|
<aside className="sidebar">
|
||||||
<input
|
<input
|
||||||
@@ -505,7 +505,7 @@ const Sidebar = ({
|
|||||||
&& typeof document !== 'undefined'
|
&& typeof document !== 'undefined'
|
||||||
? createPortal(
|
? createPortal(
|
||||||
<div
|
<div
|
||||||
className={`menu${showTenantList ? '' : ' menu--simple'}`}
|
className={menuClassName}
|
||||||
ref={tenantMenuRef}
|
ref={tenantMenuRef}
|
||||||
role="menu"
|
role="menu"
|
||||||
aria-label="Account menu"
|
aria-label="Account menu"
|
||||||
@@ -540,7 +540,7 @@ const Sidebar = ({
|
|||||||
<div className="menu__footer">
|
<div className="menu__footer">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="menu__settings"
|
className="menu__button"
|
||||||
onClick={handleSettingsFromMenu}
|
onClick={handleSettingsFromMenu}
|
||||||
>
|
>
|
||||||
<SettingsIcon size={16} />
|
<SettingsIcon size={16} />
|
||||||
@@ -548,13 +548,14 @@ const Sidebar = ({
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="menu__logout"
|
className="menu__button menu__button--danger"
|
||||||
onClick={handleLogoutFromMenu}
|
onClick={handleLogoutFromMenu}
|
||||||
>
|
>
|
||||||
<LogoutIcon size={16} />
|
<LogoutIcon size={16} />
|
||||||
Log out
|
Log out
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{themeMenuSection}
|
||||||
</div>,
|
</div>,
|
||||||
document.body,
|
document.body,
|
||||||
)
|
)
|
||||||
@@ -760,7 +761,6 @@ const Sidebar = ({
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{themeControls ? <div className="sidebar__footer">{themeControls}</div> : null}
|
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -200,12 +200,23 @@
|
|||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__title-chevron {
|
|
||||||
transition: transform 0.2s ease;
|
.sidebar__title-button .sidebar__title-chevron {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
transition:
|
||||||
|
opacity 0.12s ease,
|
||||||
|
transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__title-button:hover .sidebar__title-chevron,
|
||||||
|
.sidebar__title-button:focus-visible .sidebar__title-chevron,
|
||||||
|
.sidebar__title-chevron.is-open {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__title-chevron.is-open {
|
.sidebar__title-chevron.is-open {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg) translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
@@ -225,10 +236,10 @@
|
|||||||
.menu__list {
|
.menu__list {
|
||||||
max-height: 260px;
|
max-height: 260px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 0.35rem 0;
|
padding: 0.35rem 0.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.15rem;
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__heading {
|
.menu__heading {
|
||||||
@@ -238,17 +249,25 @@
|
|||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu__heading--with-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.menu button.menu__item,
|
.menu button.menu__item,
|
||||||
.menu .menu__item {
|
.menu .menu__item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
gap: 0.6rem;
|
gap: 0.5rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.55rem 1rem;
|
padding: 0.45rem 0.75rem;
|
||||||
border: none;
|
border: none;
|
||||||
|
border-radius: 0.4rem;
|
||||||
background: none;
|
background: none;
|
||||||
color: inherit;
|
color: var(--sidebar-fg);
|
||||||
font: inherit;
|
font: inherit;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -267,6 +286,7 @@
|
|||||||
.menu .menu__item.active {
|
.menu .menu__item.active {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
|
background: var(--accent-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu button.menu__item:focus-visible,
|
.menu button.menu__item:focus-visible,
|
||||||
@@ -313,7 +333,50 @@
|
|||||||
border-top: none;
|
border-top: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__settings {
|
|
||||||
|
.menu__section {
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
padding: 0.35rem 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu__heading-actions {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu__slider {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--muted);
|
||||||
|
padding: 0 1rem 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu__section > .menu__slider {
|
||||||
|
margin-top: -0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu__slider input[type='range'] {
|
||||||
|
flex: 1;
|
||||||
|
accent-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu__slider-label {
|
||||||
|
min-width: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu__slider-value {
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
color: var(--fg);
|
||||||
|
min-width: 3rem;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu__button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -325,30 +388,22 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0.4rem 0.5rem;
|
padding: 0.4rem 0.5rem;
|
||||||
border-radius: 0.35rem;
|
border-radius: 0.35rem;
|
||||||
|
transition: background 0.15s ease, color 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__settings:hover,
|
.menu__button:hover,
|
||||||
.menu__settings:focus-visible {
|
.menu__button:focus-visible {
|
||||||
background: var(--sidebar-hover-bg);
|
background: var(--sidebar-hover-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__logout {
|
.menu__button--danger {
|
||||||
width: 100%;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.4rem;
|
|
||||||
border: none;
|
|
||||||
background: none;
|
|
||||||
color: var(--danger);
|
color: var(--danger);
|
||||||
font: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0.4rem 0.5rem;
|
|
||||||
border-radius: 0.35rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__logout:hover,
|
.menu__button--danger:hover,
|
||||||
.menu__logout:focus-visible {
|
.menu__button--danger:focus-visible {
|
||||||
background: var(--surface-danger-subtle);
|
background: var(--surface-danger-subtle);
|
||||||
|
color: var(--danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__search {
|
.sidebar__search {
|
||||||
|
|||||||
Reference in New Issue
Block a user