From b45c24537db2c0618626ff15a5d76ee836697e72 Mon Sep 17 00:00:00 2001
From: Jay Sitter <jsit@users.noreply.github.com>
Date: Tue, 4 Jul 2023 17:24:57 -0400
Subject: [PATCH] fix: Fix focus ring styles for radio button toggles #1772
 (#1773)

---
 .../components/common/data-type-select.tsx    |  54 ++++---
 .../components/common/listing-type-select.tsx |  77 +++++----
 src/shared/components/person/inbox.tsx        | 147 +++++++++--------
 src/shared/components/person/profile.tsx      |  22 ++-
 .../person/registration-applications.tsx      |  51 +++---
 src/shared/components/person/reports.tsx      | 148 ++++++++++--------
 src/shared/components/post/post.tsx           | 125 ++++++++-------
 7 files changed, 363 insertions(+), 261 deletions(-)

diff --git a/src/shared/components/common/data-type-select.tsx b/src/shared/components/common/data-type-select.tsx
index 6bf0666..a0393f6 100644
--- a/src/shared/components/common/data-type-select.tsx
+++ b/src/shared/components/common/data-type-select.tsx
@@ -1,3 +1,5 @@
+import { randomStr } from "@utils/helpers";
+import classNames from "classnames";
 import { Component, linkEvent } from "inferno";
 import { DataType } from "../../interfaces";
 import { I18NextService } from "../../services";
@@ -15,6 +17,8 @@ export class DataTypeSelect extends Component<
   DataTypeSelectProps,
   DataTypeSelectState
 > {
+  private id = `listing-type-input-${randomStr()}`;
+
   state: DataTypeSelectState = {
     type_: this.props.type_,
   };
@@ -31,33 +35,41 @@ export class DataTypeSelect extends Component<
 
   render() {
     return (
-      <div className="data-type-select btn-group btn-group-toggle flex-wrap">
+      <div
+        className="data-type-select btn-group btn-group-toggle flex-wrap"
+        role="group"
+      >
+        <input
+          id={`${this.id}-posts`}
+          type="radio"
+          className="btn-check"
+          value={DataType.Post}
+          checked={this.state.type_ === DataType.Post}
+          onChange={linkEvent(this, this.handleTypeChange)}
+        />
         <label
-          className={`pointer btn btn-outline-secondary 
-            ${this.state.type_ == DataType.Post && "active"}
-          `}
+          htmlFor={`${this.id}-posts`}
+          className={classNames("pointer btn btn-outline-secondary", {
+            active: this.state.type_ === DataType.Post,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={DataType.Post}
-            checked={this.state.type_ == DataType.Post}
-            onChange={linkEvent(this, this.handleTypeChange)}
-          />
           {I18NextService.i18n.t("posts")}
         </label>
+
+        <input
+          id={`${this.id}-comments`}
+          type="radio"
+          className="btn-check"
+          value={DataType.Comment}
+          checked={this.state.type_ === DataType.Comment}
+          onChange={linkEvent(this, this.handleTypeChange)}
+        />
         <label
-          className={`pointer btn btn-outline-secondary ${
-            this.state.type_ == DataType.Comment && "active"
-          }`}
+          htmlFor={`${this.id}-comments`}
+          className={classNames("pointer btn btn-outline-secondary", {
+            active: this.state.type_ === DataType.Comment,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={DataType.Comment}
-            checked={this.state.type_ == DataType.Comment}
-            onChange={linkEvent(this, this.handleTypeChange)}
-          />
           {I18NextService.i18n.t("comments")}
         </label>
       </div>
diff --git a/src/shared/components/common/listing-type-select.tsx b/src/shared/components/common/listing-type-select.tsx
index 9d0a1b9..1d917dc 100644
--- a/src/shared/components/common/listing-type-select.tsx
+++ b/src/shared/components/common/listing-type-select.tsx
@@ -1,4 +1,5 @@
 import { randomStr } from "@utils/helpers";
+import classNames from "classnames";
 import { Component, linkEvent } from "inferno";
 import { ListingType } from "lemmy-js-client";
 import { I18NextService, UserService } from "../../services";
@@ -38,60 +39,72 @@ export class ListingTypeSelect extends Component<
 
   render() {
     return (
-      <div className="listing-type-select btn-group btn-group-toggle flex-wrap">
+      <div
+        className="listing-type-select btn-group btn-group-toggle flex-wrap"
+        role="group"
+      >
         {this.props.showSubscribed && (
-          <label
-            title={I18NextService.i18n.t("subscribed_description")}
-            className={`btn btn-outline-secondary 
-            ${this.state.type_ == "Subscribed" && "active"}
-            ${!UserService.Instance.myUserInfo ? "disabled" : "pointer"}
-          `}
-          >
+          <>
             <input
               id={`${this.id}-subscribed`}
               type="radio"
               className="btn-check"
               value={"Subscribed"}
-              checked={this.state.type_ == "Subscribed"}
+              checked={this.state.type_ === "Subscribed"}
               onChange={linkEvent(this, this.handleTypeChange)}
               disabled={!UserService.Instance.myUserInfo}
             />
-            {I18NextService.i18n.t("subscribed")}
-          </label>
+            <label
+              htmlFor={`${this.id}-subscribed`}
+              title={I18NextService.i18n.t("subscribed_description")}
+              className={classNames("btn btn-outline-secondary", {
+                active: this.state.type_ === "Subscribed",
+                disabled: !UserService.Instance.myUserInfo,
+                pointer: UserService.Instance.myUserInfo,
+              })}
+            >
+              {I18NextService.i18n.t("subscribed")}
+            </label>
+          </>
         )}
         {this.props.showLocal && (
-          <label
-            title={I18NextService.i18n.t("local_description")}
-            className={`pointer btn btn-outline-secondary ${
-              this.state.type_ == "Local" && "active"
-            }`}
-          >
+          <>
             <input
               id={`${this.id}-local`}
               type="radio"
               className="btn-check"
               value={"Local"}
-              checked={this.state.type_ == "Local"}
+              checked={this.state.type_ === "Local"}
               onChange={linkEvent(this, this.handleTypeChange)}
             />
-            {I18NextService.i18n.t("local")}
-          </label>
+            <label
+              htmlFor={`${this.id}-local`}
+              title={I18NextService.i18n.t("local_description")}
+              className={classNames("pointer btn btn-outline-secondary", {
+                active: this.state.type_ === "Local",
+              })}
+            >
+              {I18NextService.i18n.t("local")}
+            </label>
+          </>
         )}
+        <input
+          id={`${this.id}-all`}
+          type="radio"
+          className="btn-check"
+          value={"All"}
+          checked={this.state.type_ === "All"}
+          onChange={linkEvent(this, this.handleTypeChange)}
+        />
         <label
           title={I18NextService.i18n.t("all_description")}
-          className={`pointer btn btn-outline-secondary ${
-            (this.state.type_ == "All" && "active") ||
-            (!this.props.showLocal && this.state.type_ == "Local" && "active")
-          }`}
+          htmlFor={`${this.id}-all`}
+          className={classNames("pointer btn btn-outline-secondary", {
+            active:
+              this.state.type_ === "All" ||
+              (!this.props.showLocal && this.state.type_) === "Local",
+          })}
         >
-          <input
-            id={`${this.id}-all`}
-            type="radio"
-            className="btn-check"
-            value={"All"}
-            checked={this.state.type_ == "All"}
-            onChange={linkEvent(this, this.handleTypeChange)}
-          />
           {I18NextService.i18n.t("all")}
         </label>
       </div>
diff --git a/src/shared/components/person/inbox.tsx b/src/shared/components/person/inbox.tsx
index 28bb071..bf246f6 100644
--- a/src/shared/components/person/inbox.tsx
+++ b/src/shared/components/person/inbox.tsx
@@ -11,8 +11,9 @@ import {
   setIsoData,
   updatePersonBlock,
 } from "@utils/app";
-import { capitalizeFirstLetter } from "@utils/helpers";
+import { capitalizeFirstLetter, randomStr } from "@utils/helpers";
 import { RouteDataResponse } from "@utils/types";
+import classNames from "classnames";
 import { Component, linkEvent } from "inferno";
 import {
   AddAdmin,
@@ -283,34 +284,41 @@ export class Inbox extends Component<any, InboxState> {
   }
 
   unreadOrAllRadios() {
+    const radioId = randomStr();
+
     return (
-      <div className="btn-group btn-group-toggle flex-wrap">
+      <div className="btn-group btn-group-toggle flex-wrap" role="group">
+        <input
+          id={`${radioId}-unread`}
+          type="radio"
+          className="btn-check"
+          value={UnreadOrAll.Unread}
+          checked={this.state.unreadOrAll === UnreadOrAll.Unread}
+          onChange={linkEvent(this, this.handleUnreadOrAllChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.unreadOrAll == UnreadOrAll.Unread && "active"}
-          `}
+          htmlFor={`${radioId}-unread`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.unreadOrAll === UnreadOrAll.Unread,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={UnreadOrAll.Unread}
-            checked={this.state.unreadOrAll == UnreadOrAll.Unread}
-            onChange={linkEvent(this, this.handleUnreadOrAllChange)}
-          />
           {I18NextService.i18n.t("unread")}
         </label>
+
+        <input
+          id={`${radioId}-all`}
+          type="radio"
+          className="btn-check"
+          value={UnreadOrAll.All}
+          checked={this.state.unreadOrAll === UnreadOrAll.All}
+          onChange={linkEvent(this, this.handleUnreadOrAllChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.unreadOrAll == UnreadOrAll.All && "active"}
-          `}
+          htmlFor={`${radioId}-all`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.unreadOrAll === UnreadOrAll.All,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={UnreadOrAll.All}
-            checked={this.state.unreadOrAll == UnreadOrAll.All}
-            onChange={linkEvent(this, this.handleUnreadOrAllChange)}
-          />
           {I18NextService.i18n.t("all")}
         </label>
       </div>
@@ -318,62 +326,75 @@ export class Inbox extends Component<any, InboxState> {
   }
 
   messageTypeRadios() {
+    const radioId = randomStr();
+
     return (
-      <div className="btn-group btn-group-toggle flex-wrap">
+      <div className="btn-group btn-group-toggle flex-wrap" role="group">
+        <input
+          id={`${radioId}-all`}
+          type="radio"
+          className="btn-check"
+          value={MessageType.All}
+          checked={this.state.messageType === MessageType.All}
+          onChange={linkEvent(this, this.handleMessageTypeChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.messageType == MessageType.All && "active"}
-          `}
+          htmlFor={`${radioId}-all`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.messageType === MessageType.All,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={MessageType.All}
-            checked={this.state.messageType == MessageType.All}
-            onChange={linkEvent(this, this.handleMessageTypeChange)}
-          />
           {I18NextService.i18n.t("all")}
         </label>
+
+        <input
+          id={`${radioId}-replies`}
+          type="radio"
+          className="btn-check"
+          value={MessageType.Replies}
+          checked={this.state.messageType === MessageType.Replies}
+          onChange={linkEvent(this, this.handleMessageTypeChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.messageType == MessageType.Replies && "active"}
-          `}
+          htmlFor={`${radioId}-replies`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.messageType === MessageType.Replies,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={MessageType.Replies}
-            checked={this.state.messageType == MessageType.Replies}
-            onChange={linkEvent(this, this.handleMessageTypeChange)}
-          />
           {I18NextService.i18n.t("replies")}
         </label>
+
+        <input
+          id={`${radioId}-mentions`}
+          type="radio"
+          className="btn-check"
+          value={MessageType.Mentions}
+          checked={this.state.messageType === MessageType.Mentions}
+          onChange={linkEvent(this, this.handleMessageTypeChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.messageType == MessageType.Mentions && "active"}
-          `}
+          htmlFor={`${radioId}-mentions`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.messageType === MessageType.Mentions,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={MessageType.Mentions}
-            checked={this.state.messageType == MessageType.Mentions}
-            onChange={linkEvent(this, this.handleMessageTypeChange)}
-          />
           {I18NextService.i18n.t("mentions")}
         </label>
+
+        <input
+          id={`${radioId}-messages`}
+          type="radio"
+          className="btn-check"
+          value={MessageType.Messages}
+          checked={this.state.messageType === MessageType.Messages}
+          onChange={linkEvent(this, this.handleMessageTypeChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.messageType == MessageType.Messages && "active"}
-          `}
+          htmlFor={`${radioId}-messages`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.messageType === MessageType.Messages,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={MessageType.Messages}
-            checked={this.state.messageType == MessageType.Messages}
-            onChange={linkEvent(this, this.handleMessageTypeChange)}
-          />
           {I18NextService.i18n.t("messages")}
         </label>
       </div>
diff --git a/src/shared/components/person/profile.tsx b/src/shared/components/person/profile.tsx
index 96ac3da..39979e2 100644
--- a/src/shared/components/person/profile.tsx
+++ b/src/shared/components/person/profile.tsx
@@ -18,6 +18,7 @@ import {
   getQueryParams,
   getQueryString,
   numToSI,
+  randomStr,
 } from "@utils/helpers";
 import { canMod, isAdmin, isBanned } from "@utils/roles";
 import type { QueryParams } from "@utils/types";
@@ -397,7 +398,7 @@ export class Profile extends Component<
 
   get viewRadios() {
     return (
-      <div className="btn-group btn-group-toggle flex-wrap mb-2">
+      <div className="btn-group btn-group-toggle flex-wrap mb-2" role="group">
         {this.getRadio(PersonDetailsView.Overview)}
         {this.getRadio(PersonDetailsView.Comments)}
         {this.getRadio(PersonDetailsView.Posts)}
@@ -409,22 +410,27 @@ export class Profile extends Component<
   getRadio(view: PersonDetailsView) {
     const { view: urlView } = getProfileQueryParams();
     const active = view === urlView;
+    const radioId = randomStr();
 
     return (
-      <label
-        className={classNames("btn btn-outline-secondary pointer", {
-          active,
-        })}
-      >
+      <>
         <input
+          id={radioId}
           type="radio"
           className="btn-check"
           value={view}
           checked={active}
           onChange={linkEvent(this, this.handleViewChange)}
         />
-        {I18NextService.i18n.t(view.toLowerCase() as NoOptionI18nKeys)}
-      </label>
+        <label
+          htmlFor={radioId}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active,
+          })}
+        >
+          {I18NextService.i18n.t(view.toLowerCase() as NoOptionI18nKeys)}
+        </label>
+      </>
     );
   }
 
diff --git a/src/shared/components/person/registration-applications.tsx b/src/shared/components/person/registration-applications.tsx
index a26dd79..757170f 100644
--- a/src/shared/components/person/registration-applications.tsx
+++ b/src/shared/components/person/registration-applications.tsx
@@ -3,7 +3,9 @@ import {
   myAuthRequired,
   setIsoData,
 } from "@utils/app";
+import { randomStr } from "@utils/helpers";
 import { RouteDataResponse } from "@utils/types";
+import classNames from "classnames";
 import { Component, linkEvent } from "inferno";
 import {
   ApproveRegistrationApplication,
@@ -125,34 +127,41 @@ export class RegistrationApplications extends Component<
   }
 
   unreadOrAllRadios() {
+    const radioId = randomStr();
+
     return (
-      <div className="btn-group btn-group-toggle flex-wrap mb-2">
+      <div className="btn-group btn-group-toggle flex-wrap mb-2" role="group">
+        <input
+          id={`${radioId}-unread`}
+          type="radio"
+          className="btn-check"
+          value={UnreadOrAll.Unread}
+          checked={this.state.unreadOrAll === UnreadOrAll.Unread}
+          onChange={linkEvent(this, this.handleUnreadOrAllChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.unreadOrAll == UnreadOrAll.Unread && "active"}
-          `}
+          htmlFor={`${radioId}-unread`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.unreadOrAll === UnreadOrAll.Unread,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={UnreadOrAll.Unread}
-            checked={this.state.unreadOrAll == UnreadOrAll.Unread}
-            onChange={linkEvent(this, this.handleUnreadOrAllChange)}
-          />
           {I18NextService.i18n.t("unread")}
         </label>
+
+        <input
+          id={`${radioId}-all`}
+          type="radio"
+          className="btn-check"
+          value={UnreadOrAll.All}
+          checked={this.state.unreadOrAll === UnreadOrAll.All}
+          onChange={linkEvent(this, this.handleUnreadOrAllChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.unreadOrAll == UnreadOrAll.All && "active"}
-          `}
+          htmlFor={`${radioId}-all`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.unreadOrAll === UnreadOrAll.All,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={UnreadOrAll.All}
-            checked={this.state.unreadOrAll == UnreadOrAll.All}
-            onChange={linkEvent(this, this.handleUnreadOrAllChange)}
-          />
           {I18NextService.i18n.t("all")}
         </label>
       </div>
diff --git a/src/shared/components/person/reports.tsx b/src/shared/components/person/reports.tsx
index c16b17a..d298930 100644
--- a/src/shared/components/person/reports.tsx
+++ b/src/shared/components/person/reports.tsx
@@ -5,8 +5,10 @@ import {
   myAuthRequired,
   setIsoData,
 } from "@utils/app";
+import { randomStr } from "@utils/helpers";
 import { amAdmin } from "@utils/roles";
 import { RouteDataResponse } from "@utils/types";
+import classNames from "classnames";
 import { Component, linkEvent } from "inferno";
 import {
   CommentReportResponse,
@@ -187,34 +189,41 @@ export class Reports extends Component<any, ReportsState> {
   }
 
   unreadOrAllRadios() {
+    const radioId = randomStr();
+
     return (
-      <div className="btn-group btn-group-toggle flex-wrap mb-2">
+      <div className="btn-group btn-group-toggle flex-wrap mb-2" role="group">
+        <input
+          id={`${radioId}-unread`}
+          type="radio"
+          className="btn-check"
+          value={UnreadOrAll.Unread}
+          checked={this.state.unreadOrAll === UnreadOrAll.Unread}
+          onChange={linkEvent(this, this.handleUnreadOrAllChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.unreadOrAll == UnreadOrAll.Unread && "active"}
-          `}
+          htmlFor={`${radioId}-unread`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.unreadOrAll === UnreadOrAll.Unread,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={UnreadOrAll.Unread}
-            checked={this.state.unreadOrAll == UnreadOrAll.Unread}
-            onChange={linkEvent(this, this.handleUnreadOrAllChange)}
-          />
           {I18NextService.i18n.t("unread")}
         </label>
+
+        <input
+          id={`${radioId}-all`}
+          type="radio"
+          className="btn-check"
+          value={UnreadOrAll.All}
+          checked={this.state.unreadOrAll === UnreadOrAll.All}
+          onChange={linkEvent(this, this.handleUnreadOrAllChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.unreadOrAll == UnreadOrAll.All && "active"}
-          `}
+          htmlFor={`${radioId}-all`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.unreadOrAll === UnreadOrAll.All,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={UnreadOrAll.All}
-            checked={this.state.unreadOrAll == UnreadOrAll.All}
-            onChange={linkEvent(this, this.handleUnreadOrAllChange)}
-          />
           {I18NextService.i18n.t("all")}
         </label>
       </div>
@@ -222,70 +231,83 @@ export class Reports extends Component<any, ReportsState> {
   }
 
   messageTypeRadios() {
+    const radioId = randomStr();
+
     return (
-      <div className="btn-group btn-group-toggle flex-wrap mb-2">
+      <div className="btn-group btn-group-toggle flex-wrap mb-2" role="group">
+        <input
+          id={`${radioId}-all`}
+          type="radio"
+          className="btn-check"
+          value={MessageType.All}
+          checked={this.state.messageType === MessageType.All}
+          onChange={linkEvent(this, this.handleMessageTypeChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.messageType == MessageType.All && "active"}
-          `}
+          htmlFor={`${radioId}-all`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.messageType === MessageType.All,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={MessageType.All}
-            checked={this.state.messageType == MessageType.All}
-            onChange={linkEvent(this, this.handleMessageTypeChange)}
-          />
           {I18NextService.i18n.t("all")}
         </label>
+
+        <input
+          id={`${radioId}-comments`}
+          type="radio"
+          className="btn-check"
+          value={MessageType.CommentReport}
+          checked={this.state.messageType === MessageType.CommentReport}
+          onChange={linkEvent(this, this.handleMessageTypeChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.messageType == MessageType.CommentReport && "active"}
-          `}
+          htmlFor={`${radioId}-comments`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.messageType === MessageType.CommentReport,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={MessageType.CommentReport}
-            checked={this.state.messageType == MessageType.CommentReport}
-            onChange={linkEvent(this, this.handleMessageTypeChange)}
-          />
           {I18NextService.i18n.t("comments")}
         </label>
+
+        <input
+          id={`${radioId}-posts`}
+          type="radio"
+          className="btn-check"
+          value={MessageType.PostReport}
+          checked={this.state.messageType === MessageType.PostReport}
+          onChange={linkEvent(this, this.handleMessageTypeChange)}
+        />
         <label
-          className={`btn btn-outline-secondary pointer
-            ${this.state.messageType == MessageType.PostReport && "active"}
-          `}
+          htmlFor={`${radioId}-posts`}
+          className={classNames("btn btn-outline-secondary pointer", {
+            active: this.state.messageType === MessageType.PostReport,
+          })}
         >
-          <input
-            type="radio"
-            className="btn-check"
-            value={MessageType.PostReport}
-            checked={this.state.messageType == MessageType.PostReport}
-            onChange={linkEvent(this, this.handleMessageTypeChange)}
-          />
           {I18NextService.i18n.t("posts")}
         </label>
+
         {amAdmin() && (
-          <label
-            className={`btn btn-outline-secondary pointer
-            ${
-              this.state.messageType == MessageType.PrivateMessageReport &&
-              "active"
-            }
-          `}
-          >
+          <>
             <input
+              id={`${radioId}-messages`}
               type="radio"
               className="btn-check"
               value={MessageType.PrivateMessageReport}
               checked={
-                this.state.messageType == MessageType.PrivateMessageReport
+                this.state.messageType === MessageType.PrivateMessageReport
               }
               onChange={linkEvent(this, this.handleMessageTypeChange)}
             />
-            {I18NextService.i18n.t("messages")}
-          </label>
+            <label
+              htmlFor={`${radioId}-messages`}
+              className={classNames("btn btn-outline-secondary pointer", {
+                active:
+                  this.state.messageType === MessageType.PrivateMessageReport,
+              })}
+            >
+              {I18NextService.i18n.t("messages")}
+            </label>
+          </>
         )}
       </div>
     );
diff --git a/src/shared/components/post/post.tsx b/src/shared/components/post/post.tsx
index 3c0015e..f9d3512 100644
--- a/src/shared/components/post/post.tsx
+++ b/src/shared/components/post/post.tsx
@@ -19,10 +19,11 @@ import {
   restoreScrollPosition,
   saveScrollPosition,
 } from "@utils/browser";
-import { debounce } from "@utils/helpers";
+import { debounce, randomStr } from "@utils/helpers";
 import { isImage } from "@utils/media";
 import { RouteDataResponse } from "@utils/types";
 import autosize from "autosize";
+import classNames from "classnames";
 import { Component, RefObject, createRef, linkEvent } from "inferno";
 import {
   AddAdmin,
@@ -430,80 +431,98 @@ export class Post extends Component<any, PostState> {
   }
 
   sortRadios() {
+    const radioId =
+      this.state.postRes.state === "success"
+        ? this.state.postRes.data.post_view.post.id
+        : randomStr();
+
     return (
       <>
-        <div className="btn-group btn-group-toggle flex-wrap me-3 mb-2">
+        <div
+          className="btn-group btn-group-toggle flex-wrap me-3 mb-2"
+          role="group"
+        >
+          <input
+            id={`${radioId}-hot`}
+            type="radio"
+            className="btn-check"
+            value={"Hot"}
+            checked={this.state.commentSort === "Hot"}
+            onChange={linkEvent(this, this.handleCommentSortChange)}
+          />
           <label
-            className={`btn btn-outline-secondary pointer ${
-              this.state.commentSort === "Hot" && "active"
-            }`}
+            htmlFor={`${radioId}-hot`}
+            className={classNames("btn btn-outline-secondary pointer", {
+              active: this.state.commentSort === "Hot",
+            })}
           >
             {I18NextService.i18n.t("hot")}
-            <input
-              type="radio"
-              className="btn-check"
-              value={"Hot"}
-              checked={this.state.commentSort === "Hot"}
-              onChange={linkEvent(this, this.handleCommentSortChange)}
-            />
           </label>
+          <input
+            id={`${radioId}-top`}
+            type="radio"
+            className="btn-check"
+            value={"Top"}
+            checked={this.state.commentSort === "Top"}
+            onChange={linkEvent(this, this.handleCommentSortChange)}
+          />
           <label
-            className={`btn btn-outline-secondary pointer ${
-              this.state.commentSort === "Top" && "active"
-            }`}
+            htmlFor={`${radioId}-top`}
+            className={classNames("btn btn-outline-secondary pointer", {
+              active: this.state.commentSort === "Top",
+            })}
           >
             {I18NextService.i18n.t("top")}
-            <input
-              type="radio"
-              className="btn-check"
-              value={"Top"}
-              checked={this.state.commentSort === "Top"}
-              onChange={linkEvent(this, this.handleCommentSortChange)}
-            />
           </label>
+          <input
+            id={`${radioId}-new`}
+            type="radio"
+            className="btn-check"
+            value={"New"}
+            checked={this.state.commentSort === "New"}
+            onChange={linkEvent(this, this.handleCommentSortChange)}
+          />
           <label
-            className={`btn btn-outline-secondary pointer ${
-              this.state.commentSort === "New" && "active"
-            }`}
+            htmlFor={`${radioId}-new`}
+            className={classNames("btn btn-outline-secondary pointer", {
+              active: this.state.commentSort === "New",
+            })}
           >
             {I18NextService.i18n.t("new")}
-            <input
-              type="radio"
-              className="btn-check"
-              value={"New"}
-              checked={this.state.commentSort === "New"}
-              onChange={linkEvent(this, this.handleCommentSortChange)}
-            />
           </label>
+          <input
+            id={`${radioId}-old`}
+            type="radio"
+            className="btn-check"
+            value={"Old"}
+            checked={this.state.commentSort === "Old"}
+            onChange={linkEvent(this, this.handleCommentSortChange)}
+          />
           <label
-            className={`btn btn-outline-secondary pointer ${
-              this.state.commentSort === "Old" && "active"
-            }`}
+            htmlFor={`${radioId}-old`}
+            className={classNames("btn btn-outline-secondary pointer", {
+              active: this.state.commentSort === "Old",
+            })}
           >
             {I18NextService.i18n.t("old")}
-            <input
-              type="radio"
-              className="btn-check"
-              value={"Old"}
-              checked={this.state.commentSort === "Old"}
-              onChange={linkEvent(this, this.handleCommentSortChange)}
-            />
           </label>
         </div>
-        <div className="btn-group btn-group-toggle flex-wrap mb-2">
+        <div className="btn-group btn-group-toggle flex-wrap mb-2" role="group">
+          <input
+            id={`${radioId}-chat`}
+            type="radio"
+            className="btn-check"
+            value={CommentViewType.Flat}
+            checked={this.state.commentViewType === CommentViewType.Flat}
+            onChange={linkEvent(this, this.handleCommentViewTypeChange)}
+          />
           <label
-            className={`btn btn-outline-secondary pointer ${
-              this.state.commentViewType === CommentViewType.Flat && "active"
-            }`}
+            htmlFor={`${radioId}-chat`}
+            className={classNames("btn btn-outline-secondary pointer", {
+              active: this.state.commentViewType === CommentViewType.Flat,
+            })}
           >
             {I18NextService.i18n.t("chat")}
-            <input
-              type="radio"
-              className="btn-check"
-              value={CommentViewType.Flat}
-              checked={this.state.commentViewType === CommentViewType.Flat}
-              onChange={linkEvent(this, this.handleCommentViewTypeChange)}
-            />
           </label>
         </div>
       </>
-- 
2.44.1