mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2025-01-11 04:25:50 +00:00
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:
commit
ad0c24f3ed
3 changed files with 160 additions and 112 deletions
|
@ -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>
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue