feat(webui): add View focus escape to Quick Access
This commit is contained in:
@@ -43,7 +43,13 @@ identifiers, temporal selection, exact View identity, View recommendations or
|
|||||||
focus, and a safe return route. Cross-tenant object references are discarded
|
focus, and a safe return route. Cross-tenant object references are discarded
|
||||||
and unknown versions fail closed. View focus applies only when at least one
|
and unknown versions fail closed. View focus applies only when at least one
|
||||||
focused tool is currently enabled, context-compatible, and authorized; a
|
focused tool is currently enabled, context-compatible, and authorized; a
|
||||||
recommendation only changes ordering and emphasis.
|
recommendation only changes ordering and emphasis. The rail identifies an
|
||||||
|
active View focus and offers **All available tools** as a temporary escape to
|
||||||
|
the complete permission-derived catalogue. This does not change the active
|
||||||
|
View, persist an override, or expose a tool that failed installation,
|
||||||
|
entitlement, policy, preference, context, surface, or permission checks. If no
|
||||||
|
focused tool is eligible, the rail explains that stale focus and falls back to
|
||||||
|
the permission-derived catalogue instead of becoming empty.
|
||||||
|
|
||||||
Each renderer performs owner-side reads and effects and explicitly reports
|
Each renderer performs owner-side reads and effects and explicitly reports
|
||||||
either a result-contract-version-1 completion with a typed owner reference or
|
either a result-contract-version-1 completion with a typed owner reference or
|
||||||
|
|||||||
@@ -121,6 +121,9 @@ DOCUMENTATION = (
|
|||||||
"Messages combines enabled Mail, Postbox, and future chat contributions in one overlay. "
|
"Messages combines enabled Mail, Postbox, and future chat contributions in one overlay. "
|
||||||
"Personal settings can reorder or hide items that remain available under system, tenant, "
|
"Personal settings can reorder or hide items that remain available under system, tenant, "
|
||||||
"permission, and View policy. Every item retains a link to its complete owning page. "
|
"permission, and View policy. Every item retains a link to its complete owning page. "
|
||||||
|
"When a View focuses the rail, the rail names that View and offers a temporary All available tools escape that "
|
||||||
|
"shows the complete permission-derived catalogue without changing the View or personal settings. If none of a "
|
||||||
|
"View's focused tools is currently available, Quick Access explains the stale focus and falls back to that catalogue. "
|
||||||
"Launch-context version 2 carries only versioned, bounded references to the current object, acting assignment, "
|
"Launch-context version 2 carries only versioned, bounded references to the current object, acting assignment, "
|
||||||
"temporal selection, exact View revision, and return location. Owner modules recheck access when a tool opens and "
|
"temporal selection, exact View revision, and return location. Owner modules recheck access when a tool opens and "
|
||||||
"before each effect. A tool returns either an explicit version-1 completion with a typed owner reference or an "
|
"before each effect. A tool returns either an explicit version-1 completion with a typed owner reference or an "
|
||||||
@@ -145,6 +148,9 @@ DOCUMENTATION = (
|
|||||||
"Eine Kategorie in der rechten Leiste oeffnet kompakte Werkzeuge, ohne die aktuelle Aufgabe zu verlassen. "
|
"Eine Kategorie in der rechten Leiste oeffnet kompakte Werkzeuge, ohne die aktuelle Aufgabe zu verlassen. "
|
||||||
"Nachrichten fuehrt Beitraege aus Mail, Postfach und kuenftigen Chat-Modulen in einer Einblendung zusammen. "
|
"Nachrichten fuehrt Beitraege aus Mail, Postfach und kuenftigen Chat-Modulen in einer Einblendung zusammen. "
|
||||||
"Persoenliche Einstellungen koennen alle durch System, Mandant, Berechtigungen und Ansicht zugelassenen Eintraege ordnen oder ausblenden. "
|
"Persoenliche Einstellungen koennen alle durch System, Mandant, Berechtigungen und Ansicht zugelassenen Eintraege ordnen oder ausblenden. "
|
||||||
|
"Wenn eine Ansicht die Leiste fokussiert, benennt die Leiste diese Ansicht und bietet voruebergehend alle "
|
||||||
|
"verfuegbaren Werkzeuge an, ohne Ansicht oder persoenliche Einstellungen zu aendern. Ist keines der fokussierten "
|
||||||
|
"Werkzeuge verfuegbar, wird der veraltete Fokus erklaert und der berechtigungsabgeleitete Katalog angezeigt. "
|
||||||
"Startkontext Version 2 uebergibt nur versionierte, begrenzte Verweise auf Objekt, handelnde Zuordnung, "
|
"Startkontext Version 2 uebergibt nur versionierte, begrenzte Verweise auf Objekt, handelnde Zuordnung, "
|
||||||
"Zeitbezug, genaue Ansichtsversion und Ruecksprungort. Das besitzende Modul prueft den Zugriff beim Oeffnen "
|
"Zeitbezug, genaue Ansichtsversion und Ruecksprungort. Das besitzende Modul prueft den Zugriff beim Oeffnen "
|
||||||
"und vor jeder Wirkung erneut. Ein Werkzeug meldet entweder einen ausdruecklichen Abschluss mit typisiertem "
|
"und vor jeder Wirkung erneut. Ein Werkzeug meldet entweder einen ausdruecklichen Abschluss mit typisiertem "
|
||||||
@@ -170,7 +176,8 @@ DOCUMENTATION = (
|
|||||||
"tenant settings constrain users. An item may remain available, be blocked, or be forced. "
|
"tenant settings constrain users. An item may remain available, be blocked, or be forced. "
|
||||||
"Views and permissions form additional ceilings and Quick Access never grants access to domain data. "
|
"Views and permissions form additional ceilings and Quick Access never grants access to domain data. "
|
||||||
"A View may recommend tools or focus the rail to a subset, but only currently enabled, context-compatible, authorized "
|
"A View may recommend tools or focus the rail to a subset, but only currently enabled, context-compatible, authorized "
|
||||||
"tools participate. Workflow receives that same presentation from the exact resolved View revision. Launch-context "
|
"tools participate. The All available tools escape only restores that permission-derived set for the current session; "
|
||||||
|
"it never broadens authorization or persists an override. Workflow receives that same presentation from the exact resolved View revision. Launch-context "
|
||||||
"version 2, reference contract version 1, and result contract version 1 fail closed on unknown versions; cross-tenant "
|
"version 2, reference contract version 1, and result contract version 1 fail closed on unknown versions; cross-tenant "
|
||||||
"active-object and result references are rejected."
|
"active-object and result references are rejected."
|
||||||
),
|
),
|
||||||
@@ -186,7 +193,8 @@ DOCUMENTATION = (
|
|||||||
"Mandanteneinstellungen begrenzen Benutzer. Ein Eintrag kann verfuegbar, gesperrt oder erzwungen sein. "
|
"Mandanteneinstellungen begrenzen Benutzer. Ein Eintrag kann verfuegbar, gesperrt oder erzwungen sein. "
|
||||||
"Ansichten und Berechtigungen bilden weitere Grenzen; Schnellzugriff erteilt selbst keinen Datenzugriff. "
|
"Ansichten und Berechtigungen bilden weitere Grenzen; Schnellzugriff erteilt selbst keinen Datenzugriff. "
|
||||||
"Eine Ansicht darf Werkzeuge empfehlen oder die Leiste auf eine Teilmenge fokussieren, jedoch nur innerhalb "
|
"Eine Ansicht darf Werkzeuge empfehlen oder die Leiste auf eine Teilmenge fokussieren, jedoch nur innerhalb "
|
||||||
"der aktivierten, kontextgeeigneten und berechtigten Werkzeuge. Workflow verwendet dieselbe Darstellung aus "
|
"der aktivierten, kontextgeeigneten und berechtigten Werkzeuge. Alle verfuegbaren Werkzeuge stellt nur diese "
|
||||||
|
"berechtigungsabgeleitete Menge fuer die laufende Sitzung wieder her und speichert keine Umgehung. Workflow verwendet dieselbe Darstellung aus "
|
||||||
"der genau aufgeloesten Ansichtsversion. Startkontext Version 2 sowie Verweis- und Ergebniskontrakt Version 1 "
|
"der genau aufgeloesten Ansichtsversion. Startkontext Version 2 sowie Verweis- und Ergebniskontrakt Version 1 "
|
||||||
"lehnen unbekannte Versionen ab; mandantenfremde Objekt- und Ergebnisverweise werden verworfen."
|
"lehnen unbekannte Versionen ab; mandantenfremde Objekt- und Ergebnisverweise werden verworfen."
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
CalendarDays,
|
CalendarDays,
|
||||||
Files,
|
Files,
|
||||||
|
Grid2X2,
|
||||||
ListChecks,
|
ListChecks,
|
||||||
|
ListFilter,
|
||||||
MessagesSquare,
|
MessagesSquare,
|
||||||
Settings2,
|
Settings2,
|
||||||
X,
|
X,
|
||||||
@@ -15,6 +17,7 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
LoadingFrame,
|
LoadingFrame,
|
||||||
dispatchQuickAccessResult,
|
dispatchQuickAccessResult,
|
||||||
|
i18nMessage,
|
||||||
quickAccessLaunchState,
|
quickAccessLaunchState,
|
||||||
useGuardedNavigate,
|
useGuardedNavigate,
|
||||||
usePlatformLanguage,
|
usePlatformLanguage,
|
||||||
@@ -39,6 +42,7 @@ const iconByCategory: Record<string, LucideIcon> = {
|
|||||||
export default function QuickAccessRail({ settings, auth, tools, launchContext }: QuickAccessRailProps) {
|
export default function QuickAccessRail({ settings, auth, tools, launchContext }: QuickAccessRailProps) {
|
||||||
const [effective, setEffective] = useState<EffectiveQuickAccess | null>(null);
|
const [effective, setEffective] = useState<EffectiveQuickAccess | null>(null);
|
||||||
const [activeCategoryId, setActiveCategoryId] = useState<string | null>(null);
|
const [activeCategoryId, setActiveCategoryId] = useState<string | null>(null);
|
||||||
|
const [showAllAvailable, setShowAllAvailable] = useState(false);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const drawerRef = useRef<HTMLDivElement>(null);
|
const drawerRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -61,8 +65,8 @@ export default function QuickAccessRail({ settings, auth, tools, launchContext }
|
|||||||
() => new Set(launchContext.viewContext?.recommendedToolIds ?? []),
|
() => new Set(launchContext.viewContext?.recommendedToolIds ?? []),
|
||||||
[launchContext.viewContext?.recommendedToolIds]
|
[launchContext.viewContext?.recommendedToolIds]
|
||||||
);
|
);
|
||||||
const categories = useMemo(() => {
|
const eligibleCategories = useMemo(() =>
|
||||||
const eligibleCategories = (effective?.categories ?? [])
|
(effective?.categories ?? [])
|
||||||
.filter((category) => category.enabled)
|
.filter((category) => category.enabled)
|
||||||
.map((category) => ({
|
.map((category) => ({
|
||||||
...category,
|
...category,
|
||||||
@@ -76,14 +80,30 @@ export default function QuickAccessRail({ settings, auth, tools, launchContext }
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
}));
|
}))
|
||||||
const hasEligibleFocus = eligibleCategories.some((category) =>
|
.filter((category) => category.tools.length > 0),
|
||||||
category.tools.some((tool) => focusedToolIds.has(tool.id))
|
[availableToolIds, effective, launchContext.activeObject, metadataById]
|
||||||
);
|
);
|
||||||
|
const hasEligibleFocus = useMemo(
|
||||||
|
() => eligibleCategories.some((category) =>
|
||||||
|
category.tools.some((tool) => focusedToolIds.has(tool.id))
|
||||||
|
),
|
||||||
|
[eligibleCategories, focusedToolIds]
|
||||||
|
);
|
||||||
|
const hiddenByFocusCount = useMemo(
|
||||||
|
() => hasEligibleFocus
|
||||||
|
? eligibleCategories.reduce(
|
||||||
|
(count, category) => count + category.tools.filter((tool) => !focusedToolIds.has(tool.id)).length,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
: 0,
|
||||||
|
[eligibleCategories, focusedToolIds, hasEligibleFocus]
|
||||||
|
);
|
||||||
|
const categories = useMemo(() => {
|
||||||
return eligibleCategories.map((category) => ({
|
return eligibleCategories.map((category) => ({
|
||||||
...category,
|
...category,
|
||||||
tools: category.tools.filter((tool) =>
|
tools: category.tools.filter((tool) =>
|
||||||
!hasEligibleFocus || focusedToolIds.has(tool.id)
|
!hasEligibleFocus || showAllAvailable || focusedToolIds.has(tool.id)
|
||||||
).sort((left, right) =>
|
).sort((left, right) =>
|
||||||
Number(recommendedToolIds.has(right.id)) - Number(recommendedToolIds.has(left.id))
|
Number(recommendedToolIds.has(right.id)) - Number(recommendedToolIds.has(left.id))
|
||||||
|| left.order - right.order
|
|| left.order - right.order
|
||||||
@@ -91,7 +111,7 @@ export default function QuickAccessRail({ settings, auth, tools, launchContext }
|
|||||||
)
|
)
|
||||||
})).filter((category) => category.enabled && category.tools.length > 0);
|
})).filter((category) => category.enabled && category.tools.length > 0);
|
||||||
},
|
},
|
||||||
[availableToolIds, effective, focusedToolIds, launchContext.activeObject, metadataById, recommendedToolIds]
|
[eligibleCategories, focusedToolIds, hasEligibleFocus, recommendedToolIds, showAllAvailable]
|
||||||
);
|
);
|
||||||
const activeCategory = categories.find((category) => category.id === activeCategoryId) ?? null;
|
const activeCategory = categories.find((category) => category.id === activeCategoryId) ?? null;
|
||||||
|
|
||||||
@@ -143,6 +163,10 @@ export default function QuickAccessRail({ settings, auth, tools, launchContext }
|
|||||||
setActiveCategoryId(null);
|
setActiveCategoryId(null);
|
||||||
}, [location.pathname, location.search]);
|
}, [location.pathname, location.search]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setShowAllAvailable(false);
|
||||||
|
}, [launchContext.viewContext?.viewId, launchContext.viewContext?.revisionId]);
|
||||||
|
|
||||||
if (!loading && categories.length === 0 && !error) return null;
|
if (!loading && categories.length === 0 && !error) return null;
|
||||||
|
|
||||||
function closeDrawer(restoreFocus = true) {
|
function closeDrawer(restoreFocus = true) {
|
||||||
@@ -169,9 +193,37 @@ export default function QuickAccessRail({ settings, auth, tools, launchContext }
|
|||||||
navigate(path, { state: quickAccessLaunchState(launchContext) });
|
navigate(path, { state: quickAccessLaunchState(launchContext) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleViewFocus() {
|
||||||
|
setShowAllAvailable((current) => !current);
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewName = launchContext.viewContext?.name?.trim()
|
||||||
|
|| translateText("i18n:govoplan-quick-access.current_view");
|
||||||
|
const viewFocusRequested = focusedToolIds.size > 0;
|
||||||
|
const canToggleViewFocus = hasEligibleFocus && hiddenByFocusCount > 0;
|
||||||
|
const viewModeLabel = showAllAvailable
|
||||||
|
? translateText("i18n:govoplan-quick-access.restore_view_focus")
|
||||||
|
: translateText("i18n:govoplan-quick-access.show_all_available");
|
||||||
|
const viewModeExplanation = !hasEligibleFocus
|
||||||
|
? translateText(i18nMessage("i18n:govoplan-quick-access.focus_unavailable", { value0: viewName }))
|
||||||
|
: showAllAvailable
|
||||||
|
? translateText(i18nMessage("i18n:govoplan-quick-access.showing_all_for_view", { value0: viewName }))
|
||||||
|
: translateText(i18nMessage("i18n:govoplan-quick-access.focused_by_view", { value0: viewName }));
|
||||||
|
const viewFocusMode = !viewFocusRequested
|
||||||
|
? "none"
|
||||||
|
: !hasEligibleFocus
|
||||||
|
? "unavailable"
|
||||||
|
: showAllAvailable
|
||||||
|
? "all"
|
||||||
|
: "focused";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<aside className="quick-access-rail" aria-label="i18n:govoplan-quick-access.quick_access">
|
<aside
|
||||||
|
className="quick-access-rail"
|
||||||
|
aria-label="i18n:govoplan-quick-access.quick_access"
|
||||||
|
data-view-focus-mode={viewFocusMode}
|
||||||
|
>
|
||||||
<div className="quick-access-rail-tools">
|
<div className="quick-access-rail-tools">
|
||||||
{loading ? <span className="quick-access-rail-loading" aria-label="i18n:govoplan-quick-access.loading" /> : null}
|
{loading ? <span className="quick-access-rail-loading" aria-label="i18n:govoplan-quick-access.loading" /> : null}
|
||||||
{categories.map((category) => {
|
{categories.map((category) => {
|
||||||
@@ -193,6 +245,20 @@ export default function QuickAccessRail({ settings, auth, tools, launchContext }
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
{canToggleViewFocus ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`quick-access-rail-button quick-access-view-mode-button${showAllAvailable ? " active" : ""}`}
|
||||||
|
title={viewModeLabel}
|
||||||
|
aria-label={viewModeLabel}
|
||||||
|
aria-pressed={showAllAvailable}
|
||||||
|
onClick={toggleViewFocus}
|
||||||
|
>
|
||||||
|
{showAllAvailable
|
||||||
|
? <ListFilter size={19} aria-hidden="true" />
|
||||||
|
: <Grid2X2 size={19} aria-hidden="true" />}
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
<Link
|
<Link
|
||||||
className="quick-access-rail-button quick-access-settings-link"
|
className="quick-access-rail-button quick-access-settings-link"
|
||||||
to="/settings?section=quick-access"
|
to="/settings?section=quick-access"
|
||||||
@@ -220,6 +286,14 @@ export default function QuickAccessRail({ settings, auth, tools, launchContext }
|
|||||||
<IconButton label="i18n:govoplan-quick-access.close" icon={<X size={18} />} variant="ghost" onClick={() => closeDrawer()} />
|
<IconButton label="i18n:govoplan-quick-access.close" icon={<X size={18} />} variant="ghost" onClick={() => closeDrawer()} />
|
||||||
</header>
|
</header>
|
||||||
<div className="quick-access-drawer-content">
|
<div className="quick-access-drawer-content">
|
||||||
|
{viewFocusRequested ? (
|
||||||
|
<div className="quick-access-view-mode" role="status" data-view-focus-mode={viewFocusMode}>
|
||||||
|
<span>{viewModeExplanation}</span>
|
||||||
|
{canToggleViewFocus ? (
|
||||||
|
<button type="button" onClick={toggleViewFocus}>{viewModeLabel}</button>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
{error ? <DismissibleAlert tone="warning" resetKey={error}>{error}</DismissibleAlert> : null}
|
{error ? <DismissibleAlert tone="warning" resetKey={error}>{error}</DismissibleAlert> : null}
|
||||||
<LoadingFrame loading={loading} label="i18n:govoplan-quick-access.loading">
|
<LoadingFrame loading={loading} label="i18n:govoplan-quick-access.loading">
|
||||||
{activeCategory.tools.map((tool) => {
|
{activeCategory.tools.map((tool) => {
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ export const generatedTranslations: PlatformTranslations = {
|
|||||||
"i18n:govoplan-quick-access.open_full_page": "Vollständige Seite öffnen",
|
"i18n:govoplan-quick-access.open_full_page": "Vollständige Seite öffnen",
|
||||||
"i18n:govoplan-quick-access.compact_view_unavailable": "Die kompakte Ansicht ist nicht verfügbar. Verwenden Sie die vollständige Seite.",
|
"i18n:govoplan-quick-access.compact_view_unavailable": "Die kompakte Ansicht ist nicht verfügbar. Verwenden Sie die vollständige Seite.",
|
||||||
"i18n:govoplan-quick-access.recommended_for_view": "Für diese Ansicht empfohlen",
|
"i18n:govoplan-quick-access.recommended_for_view": "Für diese Ansicht empfohlen",
|
||||||
|
"i18n:govoplan-quick-access.current_view": "aktuelle Ansicht",
|
||||||
|
"i18n:govoplan-quick-access.show_all_available": "Alle verfügbaren Werkzeuge anzeigen",
|
||||||
|
"i18n:govoplan-quick-access.restore_view_focus": "Ansichtsfokus wiederherstellen",
|
||||||
|
"i18n:govoplan-quick-access.focused_by_view": "Durch die Ansicht {value0} fokussiert. Weitere berechtigte Werkzeuge bleiben verfügbar.",
|
||||||
|
"i18n:govoplan-quick-access.showing_all_for_view": "Alle für Sie verfügbaren Werkzeuge werden angezeigt; die Ansicht {value0} bleibt aktiv.",
|
||||||
|
"i18n:govoplan-quick-access.focus_unavailable": "Der Werkzeugfokus der Ansicht {value0} ist derzeit nicht verfügbar. Alle berechtigten Werkzeuge werden angezeigt.",
|
||||||
"i18n:govoplan-quick-access.invalid_result": "Das Werkzeug hat ein ungültiges oder nicht zugelassenes Ergebnis zurückgegeben.",
|
"i18n:govoplan-quick-access.invalid_result": "Das Werkzeug hat ein ungültiges oder nicht zugelassenes Ergebnis zurückgegeben.",
|
||||||
"i18n:govoplan-quick-access.settings_title": "Schnellzugriff",
|
"i18n:govoplan-quick-access.settings_title": "Schnellzugriff",
|
||||||
"i18n:govoplan-quick-access.personal_help": "Werkzeuge auswählen und ordnen, die neben der aktuellen Arbeit verfügbar bleiben.",
|
"i18n:govoplan-quick-access.personal_help": "Werkzeuge auswählen und ordnen, die neben der aktuellen Arbeit verfügbar bleiben.",
|
||||||
@@ -48,6 +54,12 @@ export const generatedTranslations: PlatformTranslations = {
|
|||||||
"i18n:govoplan-quick-access.open_full_page": "Open full page",
|
"i18n:govoplan-quick-access.open_full_page": "Open full page",
|
||||||
"i18n:govoplan-quick-access.compact_view_unavailable": "The compact view is unavailable. Use the full page.",
|
"i18n:govoplan-quick-access.compact_view_unavailable": "The compact view is unavailable. Use the full page.",
|
||||||
"i18n:govoplan-quick-access.recommended_for_view": "Recommended for this View",
|
"i18n:govoplan-quick-access.recommended_for_view": "Recommended for this View",
|
||||||
|
"i18n:govoplan-quick-access.current_view": "current View",
|
||||||
|
"i18n:govoplan-quick-access.show_all_available": "Show all available tools",
|
||||||
|
"i18n:govoplan-quick-access.restore_view_focus": "Restore View focus",
|
||||||
|
"i18n:govoplan-quick-access.focused_by_view": "Focused by the {value0} View. Other authorized tools remain available.",
|
||||||
|
"i18n:govoplan-quick-access.showing_all_for_view": "Showing all tools available to you; the {value0} View remains active.",
|
||||||
|
"i18n:govoplan-quick-access.focus_unavailable": "The {value0} View's tool focus is currently unavailable. All authorized tools are shown.",
|
||||||
"i18n:govoplan-quick-access.invalid_result": "The tool returned an invalid or undeclared result.",
|
"i18n:govoplan-quick-access.invalid_result": "The tool returned an invalid or undeclared result.",
|
||||||
"i18n:govoplan-quick-access.settings_title": "Quick Access",
|
"i18n:govoplan-quick-access.settings_title": "Quick Access",
|
||||||
"i18n:govoplan-quick-access.personal_help": "Choose and order the tools kept beside your current work.",
|
"i18n:govoplan-quick-access.personal_help": "Choose and order the tools kept beside your current work.",
|
||||||
|
|||||||
@@ -55,6 +55,15 @@
|
|||||||
margin: auto 4px 6px;
|
margin: auto 4px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-access-view-mode-button {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin: auto 4px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-access-view-mode-button + .quick-access-settings-link {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.quick-access-rail-loading {
|
.quick-access-rail-loading {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
@@ -117,6 +126,36 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-access-view-mode {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
border-bottom: var(--border-line);
|
||||||
|
padding: 9px 12px 9px 16px;
|
||||||
|
background: var(--accent-soft);
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-access-view-mode button {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border: 0;
|
||||||
|
padding: 2px 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--accent);
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-access-view-mode button:hover,
|
||||||
|
.quick-access-view-mode button:focus-visible {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.quick-access-tool {
|
.quick-access-tool {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
@@ -270,6 +309,14 @@
|
|||||||
margin: 4px 6px 4px auto;
|
margin: 4px 6px 4px auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-access-view-mode-button {
|
||||||
|
margin: 4px 3px 4px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-access-view-mode-button + .quick-access-settings-link {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.quick-access-drawer {
|
.quick-access-drawer {
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 50px;
|
bottom: 50px;
|
||||||
@@ -281,6 +328,11 @@
|
|||||||
box-shadow: var(--shadow-drawer-bottom);
|
box-shadow: var(--shadow-drawer-bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-access-view-mode {
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.quick-access-preference-row {
|
.quick-access-preference-row {
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
Reference in New Issue
Block a user