mirror of
https://github.com/github/awesome-copilot.git
synced 2026-08-25 10:21:40 +00:00
fix(website): collapse long filter facets and unpin detail-page footer
Two issues surfaced by review of the redesigned site: Catalog facets rendered every option. The prototype's filter groups were built from small hardcoded arrays, but real data produces 193 tool options on /agents/ and 245 "Applies to" values on /instructions/. The sidebar grew to ~10,000px and stretched the whole catalog row, pushing the (already present) pagination control far below the fold so it read as missing. Adopt the prototype's own solution for this, which it had already applied to the extensions page: collapse groups past 10 options behind a "Show N more" toggle, and cap .filterOptions with an internal scroll area. Ported verbatim to the agents, instructions, skills, and plugins catalogs. Detail pages scroll inside .scrollHost rather than the document, but the footer came from PageShell, outside that element, so it stayed pinned over the content instead of appearing at the end. The prototype renders its footer inside the scroll host; PageShell now takes a renderFooter flag so DetailChassis can do the same. LearningArticleLayout already did this. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6
This commit is contained in:
@@ -88,6 +88,13 @@ const emptyFilters: FilterState = { model: [], tools: [], updated: [] };
|
||||
|
||||
const PAGE_SIZE = 6;
|
||||
|
||||
/**
|
||||
* Long facets collapse behind a "Show N more" toggle, matching the prototype's
|
||||
* extensions page. Real data produces far longer option lists than the
|
||||
* prototype's hardcoded arrays, so every catalog needs this.
|
||||
*/
|
||||
const FILTER_COLLAPSE_LIMIT = 10;
|
||||
|
||||
/**
|
||||
* The Agents catalog, ported from the design prototype's `agents.tsx`. The
|
||||
* prototype's hardcoded array and hardcoded model/capability options are
|
||||
@@ -109,6 +116,12 @@ export function AgentsCatalog({
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
|
||||
const [filters, setFilters] = useState<FilterState>(emptyFilters);
|
||||
const [expandedGroups, setExpandedGroups] = useState<
|
||||
Record<FilterGroupId, boolean>
|
||||
>({ model: false, tools: false, updated: false });
|
||||
const toggleGroupExpanded = (groupId: FilterGroupId) => {
|
||||
setExpandedGroups((prev) => ({ ...prev, [groupId]: !prev[groupId] }));
|
||||
};
|
||||
|
||||
const filterGroups = useMemo<
|
||||
{ id: FilterGroupId; label: string; options: string[] }[]
|
||||
@@ -257,26 +270,47 @@ export function AgentsCatalog({
|
||||
!mobileFiltersOpen && styles.filterBodyCollapsed,
|
||||
)}
|
||||
>
|
||||
{filterGroups.map((group) => (
|
||||
<div className={styles.filterGroup} key={group.id}>
|
||||
<Text as="h2" size="100" className={styles.filterHeading}>
|
||||
{group.label}
|
||||
</Text>
|
||||
<div className={styles.filterOptions}>
|
||||
{group.options.map((option) => (
|
||||
<div className={styles.filterOption} key={option}>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={filters[group.id].includes(option)}
|
||||
onChange={() => toggleFilter(group.id, option)}
|
||||
/>
|
||||
<FormControl.Label>{option}</FormControl.Label>
|
||||
</FormControl>
|
||||
</div>
|
||||
))}
|
||||
{filterGroups.map((group) => {
|
||||
const isExpandable =
|
||||
group.options.length > FILTER_COLLAPSE_LIMIT;
|
||||
const expanded = expandedGroups[group.id];
|
||||
const visibleOptions =
|
||||
isExpandable && !expanded
|
||||
? group.options.slice(0, FILTER_COLLAPSE_LIMIT)
|
||||
: group.options;
|
||||
return (
|
||||
<div className={styles.filterGroup} key={group.id}>
|
||||
<Text as="h2" size="100" className={styles.filterHeading}>
|
||||
{group.label}
|
||||
</Text>
|
||||
<div className={styles.filterOptions}>
|
||||
{visibleOptions.map((option) => (
|
||||
<div className={styles.filterOption} key={option}>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={filters[group.id].includes(option)}
|
||||
onChange={() => toggleFilter(group.id, option)}
|
||||
/>
|
||||
<FormControl.Label>{option}</FormControl.Label>
|
||||
</FormControl>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{isExpandable ? (
|
||||
<button
|
||||
type="button"
|
||||
className={styles.showMoreButton}
|
||||
aria-expanded={expanded}
|
||||
onClick={() => toggleGroupExpanded(group.id)}
|
||||
>
|
||||
{expanded
|
||||
? "Show less"
|
||||
: `Show ${group.options.length - FILTER_COLLAPSE_LIMIT} more`}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
{hasActiveFilters ? (
|
||||
<div className={styles.filterActions}>
|
||||
<Button
|
||||
|
||||
@@ -5,6 +5,7 @@ import React from "react";
|
||||
import { Box, Breadcrumbs, Heading, Section, Text } from "@primer/react-brand";
|
||||
|
||||
import { PageShell } from "./PageShell";
|
||||
import { LargeFooter } from "./LargeFooter";
|
||||
import type { AwesomeCopilotPage } from "./navigation";
|
||||
import type { SearchItem } from "./searchIndex";
|
||||
import styles from "./styles/dotnet-upgrade.module.css";
|
||||
@@ -105,6 +106,7 @@ export function DetailChassis({
|
||||
currentPage={currentPage}
|
||||
searchIndex={searchIndex}
|
||||
contributorsTotal={contributorsTotal}
|
||||
renderFooter={false}
|
||||
>
|
||||
<div className={styles.scrollHost} ref={contentScrollRef}>
|
||||
<Box as="section" className={styles.hero}>
|
||||
@@ -259,6 +261,7 @@ export function DetailChassis({
|
||||
</div>
|
||||
</Section>
|
||||
</Box>
|
||||
<LargeFooter />
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -86,6 +86,13 @@ const emptyFilters: FilterState = { pattern: [], extension: [], updated: [] };
|
||||
|
||||
const PAGE_SIZE = 6;
|
||||
|
||||
/**
|
||||
* Long facets collapse behind a "Show N more" toggle, matching the prototype's
|
||||
* extensions page. Real data produces far longer option lists than the
|
||||
* prototype's hardcoded arrays, so every catalog needs this.
|
||||
*/
|
||||
const FILTER_COLLAPSE_LIMIT = 10;
|
||||
|
||||
/**
|
||||
* The Instructions catalog, ported from the design prototype's
|
||||
* `instructions.tsx`. The prototype's hardcoded array and filter options are
|
||||
@@ -108,6 +115,12 @@ export function InstructionsCatalog({
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
|
||||
const [filters, setFilters] = useState<FilterState>(emptyFilters);
|
||||
const [expandedGroups, setExpandedGroups] = useState<
|
||||
Record<FilterGroupId, boolean>
|
||||
>({ pattern: false, extension: false, updated: false });
|
||||
const toggleGroupExpanded = (groupId: FilterGroupId) => {
|
||||
setExpandedGroups((prev) => ({ ...prev, [groupId]: !prev[groupId] }));
|
||||
};
|
||||
|
||||
const filterGroups = useMemo<
|
||||
{ id: FilterGroupId; label: string; options: string[] }[]
|
||||
@@ -388,26 +401,47 @@ export function InstructionsCatalog({
|
||||
!mobileFiltersOpen && styles.filterBodyCollapsed,
|
||||
)}
|
||||
>
|
||||
{filterGroups.map((group) => (
|
||||
<div className={styles.filterGroup} key={group.id}>
|
||||
<Text as="h2" size="100" className={styles.filterHeading}>
|
||||
{group.label}
|
||||
</Text>
|
||||
<div className={styles.filterOptions}>
|
||||
{group.options.map((option) => (
|
||||
<div className={styles.filterOption} key={option}>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={filters[group.id].includes(option)}
|
||||
onChange={() => toggleFilter(group.id, option)}
|
||||
/>
|
||||
<FormControl.Label>{option}</FormControl.Label>
|
||||
</FormControl>
|
||||
</div>
|
||||
))}
|
||||
{filterGroups.map((group) => {
|
||||
const isExpandable =
|
||||
group.options.length > FILTER_COLLAPSE_LIMIT;
|
||||
const expanded = expandedGroups[group.id];
|
||||
const visibleOptions =
|
||||
isExpandable && !expanded
|
||||
? group.options.slice(0, FILTER_COLLAPSE_LIMIT)
|
||||
: group.options;
|
||||
return (
|
||||
<div className={styles.filterGroup} key={group.id}>
|
||||
<Text as="h2" size="100" className={styles.filterHeading}>
|
||||
{group.label}
|
||||
</Text>
|
||||
<div className={styles.filterOptions}>
|
||||
{visibleOptions.map((option) => (
|
||||
<div className={styles.filterOption} key={option}>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={filters[group.id].includes(option)}
|
||||
onChange={() => toggleFilter(group.id, option)}
|
||||
/>
|
||||
<FormControl.Label>{option}</FormControl.Label>
|
||||
</FormControl>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{isExpandable ? (
|
||||
<button
|
||||
type="button"
|
||||
className={styles.showMoreButton}
|
||||
aria-expanded={expanded}
|
||||
onClick={() => toggleGroupExpanded(group.id)}
|
||||
>
|
||||
{expanded
|
||||
? "Show less"
|
||||
: `Show ${group.options.length - FILTER_COLLAPSE_LIMIT} more`}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
{hasActiveFilters ? (
|
||||
<div className={styles.filterActions}>
|
||||
<Button
|
||||
|
||||
@@ -26,6 +26,13 @@ export type PageShellProps = {
|
||||
contributorsTotal?: number;
|
||||
searchAriaLabel?: string;
|
||||
contributorsCurrent?: boolean;
|
||||
/**
|
||||
* Pages that scroll inside their own element (the detail/article chassis) must
|
||||
* render the footer *inside* that scroll region, otherwise it sits outside the
|
||||
* scrolling box and stays pinned over the content. Those pages opt out here
|
||||
* and render `<LargeFooter />` themselves.
|
||||
*/
|
||||
renderFooter?: boolean;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
@@ -44,6 +51,7 @@ export function PageShell({
|
||||
contributorsTotal = 0,
|
||||
searchAriaLabel = "Search the library",
|
||||
contributorsCurrent = false,
|
||||
renderFooter = true,
|
||||
children,
|
||||
}: PageShellProps) {
|
||||
return (
|
||||
@@ -55,6 +63,7 @@ export function PageShell({
|
||||
contributorsTotal={contributorsTotal}
|
||||
searchAriaLabel={searchAriaLabel}
|
||||
contributorsCurrent={contributorsCurrent}
|
||||
renderFooter={renderFooter}
|
||||
>
|
||||
{children}
|
||||
</PageShellBody>
|
||||
@@ -74,6 +83,7 @@ function PageShellBody({
|
||||
contributorsTotal = 0,
|
||||
searchAriaLabel = "Search the library",
|
||||
contributorsCurrent = false,
|
||||
renderFooter = true,
|
||||
children,
|
||||
}: PageShellProps) {
|
||||
const { colorMode } = useTheme();
|
||||
@@ -121,7 +131,7 @@ function PageShellBody({
|
||||
{children}
|
||||
</main>
|
||||
|
||||
<LargeFooter />
|
||||
{renderFooter ? <LargeFooter /> : null}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,13 @@ type FilterState = Record<FilterGroupId, string[]>;
|
||||
|
||||
const emptyFilters: FilterState = { source: [], category: [], size: [] };
|
||||
|
||||
/**
|
||||
* Long facets collapse behind a "Show N more" toggle, matching the prototype's
|
||||
* extensions page. Real data produces far longer option lists than the
|
||||
* prototype's hardcoded arrays, so every catalog needs this.
|
||||
*/
|
||||
const FILTER_COLLAPSE_LIMIT = 10;
|
||||
|
||||
const sourceOf = (plugin: PluginItem) =>
|
||||
plugin.external ? "External" : "Built-in";
|
||||
|
||||
@@ -120,6 +127,12 @@ export function PluginsCatalog({
|
||||
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
|
||||
|
||||
const [filters, setFilters] = useState<FilterState>(emptyFilters);
|
||||
const [expandedGroups, setExpandedGroups] = useState<
|
||||
Record<FilterGroupId, boolean>
|
||||
>({ source: false, category: false, size: false });
|
||||
const toggleGroupExpanded = (groupId: FilterGroupId) => {
|
||||
setExpandedGroups((prev) => ({ ...prev, [groupId]: !prev[groupId] }));
|
||||
};
|
||||
|
||||
const filterGroups = useMemo(
|
||||
(): { id: FilterGroupId; label: string; options: string[] }[] => [
|
||||
@@ -226,26 +239,47 @@ export function PluginsCatalog({
|
||||
!mobileFiltersOpen && styles.filterBodyCollapsed,
|
||||
)}
|
||||
>
|
||||
{filterGroups.map((group) => (
|
||||
<div className={styles.filterGroup} key={group.id}>
|
||||
<Text as="h2" size="100" className={styles.filterHeading}>
|
||||
{group.label}
|
||||
</Text>
|
||||
<div className={styles.filterOptions}>
|
||||
{group.options.map((option) => (
|
||||
<div className={styles.filterOption} key={option}>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={filters[group.id].includes(option)}
|
||||
onChange={() => toggleFilter(group.id, option)}
|
||||
/>
|
||||
<FormControl.Label>{option}</FormControl.Label>
|
||||
</FormControl>
|
||||
</div>
|
||||
))}
|
||||
{filterGroups.map((group) => {
|
||||
const isExpandable =
|
||||
group.options.length > FILTER_COLLAPSE_LIMIT;
|
||||
const expanded = expandedGroups[group.id];
|
||||
const visibleOptions =
|
||||
isExpandable && !expanded
|
||||
? group.options.slice(0, FILTER_COLLAPSE_LIMIT)
|
||||
: group.options;
|
||||
return (
|
||||
<div className={styles.filterGroup} key={group.id}>
|
||||
<Text as="h2" size="100" className={styles.filterHeading}>
|
||||
{group.label}
|
||||
</Text>
|
||||
<div className={styles.filterOptions}>
|
||||
{visibleOptions.map((option) => (
|
||||
<div className={styles.filterOption} key={option}>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={filters[group.id].includes(option)}
|
||||
onChange={() => toggleFilter(group.id, option)}
|
||||
/>
|
||||
<FormControl.Label>{option}</FormControl.Label>
|
||||
</FormControl>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{isExpandable ? (
|
||||
<button
|
||||
type="button"
|
||||
className={styles.showMoreButton}
|
||||
aria-expanded={expanded}
|
||||
onClick={() => toggleGroupExpanded(group.id)}
|
||||
>
|
||||
{expanded
|
||||
? "Show less"
|
||||
: `Show ${group.options.length - FILTER_COLLAPSE_LIMIT} more`}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
{hasActiveFilters ? (
|
||||
<div className={styles.filterActions}>
|
||||
<Button
|
||||
|
||||
@@ -75,6 +75,13 @@ const resourceOf = (skill: SkillItem) =>
|
||||
|
||||
const PAGE_SIZE = 6;
|
||||
|
||||
/**
|
||||
* Long facets collapse behind a "Show N more" toggle, matching the prototype's
|
||||
* extensions page. Real data produces far longer option lists than the
|
||||
* prototype's hardcoded arrays, so every catalog needs this.
|
||||
*/
|
||||
const FILTER_COLLAPSE_LIMIT = 10;
|
||||
|
||||
/**
|
||||
* The Skills catalog, ported from the design prototype's `skills.tsx`. The
|
||||
* prototype's hardcoded array is replaced by build-time data; the layout,
|
||||
@@ -93,6 +100,12 @@ export function SkillsCatalog({
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
|
||||
const [filters, setFilters] = useState<FilterState>(emptyFilters);
|
||||
const [expandedGroups, setExpandedGroups] = useState<
|
||||
Record<FilterGroupId, boolean>
|
||||
>({ resources: false, files: false, updated: false });
|
||||
const toggleGroupExpanded = (groupId: FilterGroupId) => {
|
||||
setExpandedGroups((prev) => ({ ...prev, [groupId]: !prev[groupId] }));
|
||||
};
|
||||
const [copied, setCopied] = useState(false);
|
||||
const copyTimer = React.useRef<number | undefined>(undefined);
|
||||
|
||||
@@ -195,26 +208,47 @@ export function SkillsCatalog({
|
||||
!mobileFiltersOpen && styles.filterBodyCollapsed,
|
||||
)}
|
||||
>
|
||||
{filterGroups.map((group) => (
|
||||
<div className={styles.filterGroup} key={group.id}>
|
||||
<Text as="h2" size="100" className={styles.filterHeading}>
|
||||
{group.label}
|
||||
</Text>
|
||||
<div className={styles.filterOptions}>
|
||||
{group.options.map((option) => (
|
||||
<div className={styles.filterOption} key={option}>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={filters[group.id].includes(option)}
|
||||
onChange={() => toggleFilter(group.id, option)}
|
||||
/>
|
||||
<FormControl.Label>{option}</FormControl.Label>
|
||||
</FormControl>
|
||||
</div>
|
||||
))}
|
||||
{filterGroups.map((group) => {
|
||||
const isExpandable =
|
||||
group.options.length > FILTER_COLLAPSE_LIMIT;
|
||||
const expanded = expandedGroups[group.id];
|
||||
const visibleOptions =
|
||||
isExpandable && !expanded
|
||||
? group.options.slice(0, FILTER_COLLAPSE_LIMIT)
|
||||
: group.options;
|
||||
return (
|
||||
<div className={styles.filterGroup} key={group.id}>
|
||||
<Text as="h2" size="100" className={styles.filterHeading}>
|
||||
{group.label}
|
||||
</Text>
|
||||
<div className={styles.filterOptions}>
|
||||
{visibleOptions.map((option) => (
|
||||
<div className={styles.filterOption} key={option}>
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={filters[group.id].includes(option)}
|
||||
onChange={() => toggleFilter(group.id, option)}
|
||||
/>
|
||||
<FormControl.Label>{option}</FormControl.Label>
|
||||
</FormControl>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{isExpandable ? (
|
||||
<button
|
||||
type="button"
|
||||
className={styles.showMoreButton}
|
||||
aria-expanded={expanded}
|
||||
onClick={() => toggleGroupExpanded(group.id)}
|
||||
>
|
||||
{expanded
|
||||
? "Show less"
|
||||
: `Show ${group.options.length - FILTER_COLLAPSE_LIMIT} more`}
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
{hasActiveFilters ? (
|
||||
<div className={styles.filterActions}>
|
||||
<Button
|
||||
|
||||
@@ -683,6 +683,35 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--base-size-4);
|
||||
max-block-size: 480px;
|
||||
overflow-y: auto;
|
||||
padding-inline-end: var(--base-size-4);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.showMoreButton {
|
||||
align-self: flex-start;
|
||||
margin-block-start: var(--base-size-8);
|
||||
margin-inline-start: var(--base-size-12);
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
color: var(--brand-color-text-default);
|
||||
font-family: var(--brand-fontStack-monospace);
|
||||
font-size: var(--brand-text-size-100);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.showMoreButton:hover {
|
||||
color: var(--brand-color-text-muted);
|
||||
}
|
||||
|
||||
.showMoreButton:focus-visible {
|
||||
outline: var(--brand-borderWidth-thin) solid var(--brand-color-focus);
|
||||
outline-offset: var(--base-size-4);
|
||||
border-radius: var(--brand-borderRadius-small);
|
||||
}
|
||||
|
||||
.filterOption {
|
||||
|
||||
@@ -669,6 +669,35 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--base-size-4);
|
||||
max-block-size: 480px;
|
||||
overflow-y: auto;
|
||||
padding-inline-end: var(--base-size-4);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.showMoreButton {
|
||||
align-self: flex-start;
|
||||
margin-block-start: var(--base-size-8);
|
||||
margin-inline-start: var(--base-size-12);
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
color: var(--brand-color-text-default);
|
||||
font-family: var(--brand-fontStack-monospace);
|
||||
font-size: var(--brand-text-size-100);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.showMoreButton:hover {
|
||||
color: var(--brand-color-text-muted);
|
||||
}
|
||||
|
||||
.showMoreButton:focus-visible {
|
||||
outline: var(--brand-borderWidth-thin) solid var(--brand-color-focus);
|
||||
outline-offset: var(--base-size-4);
|
||||
border-radius: var(--brand-borderRadius-small);
|
||||
}
|
||||
|
||||
.filterOption {
|
||||
|
||||
@@ -767,6 +767,35 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--base-size-4);
|
||||
max-block-size: 480px;
|
||||
overflow-y: auto;
|
||||
padding-inline-end: var(--base-size-4);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.showMoreButton {
|
||||
align-self: flex-start;
|
||||
margin-block-start: var(--base-size-8);
|
||||
margin-inline-start: var(--base-size-12);
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
color: var(--brand-color-text-default);
|
||||
font-family: var(--brand-fontStack-monospace);
|
||||
font-size: var(--brand-text-size-100);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.showMoreButton:hover {
|
||||
color: var(--brand-color-text-muted);
|
||||
}
|
||||
|
||||
.showMoreButton:focus-visible {
|
||||
outline: var(--brand-borderWidth-thin) solid var(--brand-color-focus);
|
||||
outline-offset: var(--base-size-4);
|
||||
border-radius: var(--brand-borderRadius-small);
|
||||
}
|
||||
|
||||
.filterOption {
|
||||
|
||||
@@ -676,6 +676,35 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--base-size-4);
|
||||
max-block-size: 480px;
|
||||
overflow-y: auto;
|
||||
padding-inline-end: var(--base-size-4);
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.showMoreButton {
|
||||
align-self: flex-start;
|
||||
margin-block-start: var(--base-size-8);
|
||||
margin-inline-start: var(--base-size-12);
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
color: var(--brand-color-text-default);
|
||||
font-family: var(--brand-fontStack-monospace);
|
||||
font-size: var(--brand-text-size-100);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.25em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.showMoreButton:hover {
|
||||
color: var(--brand-color-text-muted);
|
||||
}
|
||||
|
||||
.showMoreButton:focus-visible {
|
||||
outline: var(--brand-borderWidth-thin) solid var(--brand-color-focus);
|
||||
outline-offset: var(--base-size-4);
|
||||
border-radius: var(--brand-borderRadius-small);
|
||||
}
|
||||
|
||||
.filterOption {
|
||||
|
||||
Reference in New Issue
Block a user