Merge pull request #1355 from jsit/fix/site-sidebar-collapse

fix(a11y): Fix some a11y issues in Site Sidebar and use native Bootstrap Collapse and Card classes
This commit is contained in:
SleeplessOne1917 2023-06-18 13:37:36 +00:00 committed by GitHub
commit ad0c24f3ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 160 additions and 112 deletions

View file

@ -15,6 +15,7 @@ export class BannerIconHeader extends Component<BannerIconHeaderProps, any> {
const banner = this.props.banner; const banner = this.props.banner;
const icon = this.props.icon; const icon = this.props.icon;
return ( return (
(banner || icon) && (
<div className="position-relative mb-2"> <div className="position-relative mb-2">
{banner && <PictrsImage src={banner} banner alt="" />} {banner && <PictrsImage src={banner} banner alt="" />}
{icon && ( {icon && (
@ -26,6 +27,7 @@ export class BannerIconHeader extends Component<BannerIconHeaderProps, any> {
/> />
)} )}
</div> </div>
)
); );
} }
} }

View file

@ -443,16 +443,17 @@ export class Home extends Component<any, HomeState> {
admins={admins} admins={admins}
counts={counts} counts={counts}
showLocal={showLocal(this.isoData)} showLocal={showLocal(this.isoData)}
isMobile={true}
/> />
)} )}
{showTrendingMobile && ( {showTrendingMobile && (
<div className="col-12 card border-secondary mb-3"> <div className="card border-secondary mb-3">
<div className="card-body">{this.trendingCommunities(true)}</div> {this.trendingCommunities()}
</div> </div>
)} )}
{showSubscribedMobile && ( {showSubscribedMobile && (
<div className="col-12 card border-secondary mb-3"> <div className="card border-secondary mb-3">
<div className="card-body">{this.subscribedCommunities}</div> {this.subscribedCommunities(true)}
</div> </div>
)} )}
</div> </div>
@ -471,8 +472,60 @@ export class Home extends Component<any, HomeState> {
return ( return (
<div id="sidebarContainer"> <div id="sidebarContainer">
<section id="sidebarMain" className="card border-secondary mb-3"> <section id="sidebarMain" className="card border-secondary mb-3">
<div className="card-body">
{this.trendingCommunities()} {this.trendingCommunities()}
</section>
<SiteSidebar
site={site}
admins={admins}
counts={counts}
showLocal={showLocal(this.isoData)}
/>
{this.hasFollows && (
<div className="accordion">
<section
id="sidebarSubscribed"
className="card border-secondary mb-3"
>
{this.subscribedCommunities(false)}
</section>
</div>
)}
</div>
);
}
trendingCommunities() {
switch (this.state.trendingCommunitiesRes?.state) {
case "loading":
return (
<h5>
<Spinner large />
</h5>
);
case "success": {
const trending = this.state.trendingCommunitiesRes.data.communities;
return (
<>
<header className="card-header d-flex align-items-center">
<h5 className="mb-0">
<T i18nKey="trending_communities">
#
<Link className="text-body" to="/communities">
#
</Link>
</T>
</h5>
</header>
<div className="card-body">
{trending.length > 0 && (
<ul className="list-inline">
{trending.map(cv => (
<li key={cv.community.id} className="list-inline-item">
<CommunityLink community={cv.community} />
</li>
))}
</ul>
)}
{canCreateCommunity(this.state.siteRes) && ( {canCreateCommunity(this.state.siteRes) && (
<LinkButton <LinkButton
path="/create_community" path="/create_community"
@ -484,86 +537,58 @@ export class Home extends Component<any, HomeState> {
translationKey="explore_communities" translationKey="explore_communities"
/> />
</div> </div>
</section> </>
<SiteSidebar
site={site}
admins={admins}
counts={counts}
showLocal={showLocal(this.isoData)}
/>
{this.hasFollows && (
<section
id="sidebarSubscribed"
className="card border-secondary mb-3"
>
<div className="card-body">{this.subscribedCommunities}</div>
</section>
)}
</div>
);
}
trendingCommunities(isMobile = false) {
switch (this.state.trendingCommunitiesRes?.state) {
case "loading":
return (
<h5>
<Spinner large />
</h5>
);
case "success": {
const trending = this.state.trendingCommunitiesRes.data.communities;
return (
<div className={!isMobile ? "mb-2" : ""}>
<h5>
<T i18nKey="trending_communities">
#
<Link className="text-body" to="/communities">
#
</Link>
</T>
</h5>
<ul className="list-inline mb-0">
{trending.map(cv => (
<li
key={cv.community.id}
className="list-inline-item d-inline-block"
>
<CommunityLink community={cv.community} />
</li>
))}
</ul>
</div>
); );
} }
} }
} }
get subscribedCommunities() { subscribedCommunities(isMobile = false) {
const { subscribedCollapsed } = this.state; const { subscribedCollapsed } = this.state;
return ( return (
<div> <>
<h5> <header
className="card-header d-flex align-items-center"
id="sidebarSubscribedHeader"
>
<h5 className="mb-0 d-inline">
<T class="d-inline" i18nKey="subscribed_to_communities"> <T class="d-inline" i18nKey="subscribed_to_communities">
# #
<Link className="text-body" to="/communities"> <Link className="text-body" to="/communities">
# #
</Link> </Link>
</T> </T>
</h5>
{!isMobile && (
<button <button
type="button"
className="btn btn-sm text-muted" className="btn btn-sm text-muted"
onClick={linkEvent(this, this.handleCollapseSubscribe)} onClick={linkEvent(this, this.handleCollapseSubscribe)}
aria-label={i18n.t("collapse")} aria-label={
data-tippy-content={i18n.t("collapse")} subscribedCollapsed ? i18n.t("expand") : i18n.t("collapse")
}
data-tippy-content={
subscribedCollapsed ? i18n.t("expand") : i18n.t("collapse")
}
data-bs-toggle="collapse"
data-bs-target="#sidebarSubscribedBody"
aria-expanded="true"
aria-controls="sidebarSubscribedBody"
> >
<Icon <Icon
icon={`${subscribedCollapsed ? "plus" : "minus"}-square`} icon={`${subscribedCollapsed ? "plus" : "minus"}-square`}
classes="icon-inline" classes="icon-inline"
/> />
</button> </button>
</h5> )}
{!subscribedCollapsed && ( </header>
<div
id="sidebarSubscribedBody"
className="collapse show"
aria-labelledby="sidebarSubscribedHeader"
>
<div className="card-body">
<ul className="list-inline mb-0"> <ul className="list-inline mb-0">
{UserService.Instance.myUserInfo?.follows.map(cfv => ( {UserService.Instance.myUserInfo?.follows.map(cfv => (
<li <li
@ -574,8 +599,9 @@ export class Home extends Component<any, HomeState> {
</li> </li>
))} ))}
</ul> </ul>
)}
</div> </div>
</div>
</>
); );
} }

View file

@ -12,6 +12,7 @@ interface SiteSidebarProps {
showLocal: boolean; showLocal: boolean;
counts?: SiteAggregates; counts?: SiteAggregates;
admins?: PersonView[]; admins?: PersonView[];
isMobile?: boolean;
} }
interface SiteSidebarState { interface SiteSidebarState {
@ -29,31 +30,49 @@ export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
render() { render() {
return ( return (
<div className="accordion">
<section id="sidebarInfo" className="card border-secondary mb-3"> <section id="sidebarInfo" className="card border-secondary mb-3">
<div className="card-body"> <header
<div> className="card-header d-flex align-items-center"
<div className="mb-2">{this.siteName()}</div> id="sidebarInfoHeader"
>
{this.siteName()}
{!this.state.collapsed && ( {!this.state.collapsed && (
<>
<BannerIconHeader banner={this.props.site.banner} /> <BannerIconHeader banner={this.props.site.banner} />
{this.siteInfo()}
</>
)} )}
</div> </header>
<div
id="sidebarInfoBody"
className="collapse show"
aria-labelledby="sidebarInfoHeader"
>
<div className="card-body">{this.siteInfo()}</div>
</div> </div>
</section> </section>
</div>
); );
} }
siteName() { siteName() {
return ( return (
<h5 className="mb-0 d-inline"> <>
{this.props.site.name} <h5 className="mb-0 d-inline">{this.props.site.name}</h5>
{!this.props.isMobile && (
<button <button
className="btn btn-sm text-muted" type="button"
className="btn btn-sm"
onClick={linkEvent(this, this.handleCollapseSidebar)} onClick={linkEvent(this, this.handleCollapseSidebar)}
aria-label={i18n.t("collapse")} aria-label={
data-tippy-content={i18n.t("collapse")} this.state.collapsed ? i18n.t("expand") : i18n.t("collapse")
}
data-tippy-content={
this.state.collapsed ? i18n.t("expand") : i18n.t("collapse")
}
data-bs-toggle="collapse"
data-bs-target="#sidebarInfoBody"
aria-expanded="true"
aria-controls="sidebarInfoBody"
> >
{this.state.collapsed ? ( {this.state.collapsed ? (
<Icon icon="plus-square" classes="icon-inline" /> <Icon icon="plus-square" classes="icon-inline" />
@ -61,7 +80,8 @@ export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
<Icon icon="minus-square" classes="icon-inline" /> <Icon icon="minus-square" classes="icon-inline" />
)} )}
</button> </button>
</h5> )}
</>
); );
} }