milestone 23 s3: convert features/groups/GroupSourcesEditor.tsx to stylex
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import { useState } from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import * as stylex from "@stylexjs/stylex";
|
||||
import { groupSourcesPutMutation, groupSourcesQuery } from "@/lib/queries";
|
||||
import type { Blocklist } from "@/lib/types";
|
||||
import { sameSet, toggleSource } from "./sourceSet";
|
||||
import InlineError from "@/lib/InlineError";
|
||||
import { buttonClass, focusRing, primaryButtonClass } from "@/ui/classes";
|
||||
import { styles as shared } from "@/ui/styles";
|
||||
import { colors } from "@/ui/tokens.stylex";
|
||||
import { READ_ONLY_HINT, useReadOnlyConfig } from "@/features/settings/authority";
|
||||
|
||||
interface Props {
|
||||
@@ -12,6 +14,35 @@ interface Props {
|
||||
blocklists: Blocklist[];
|
||||
}
|
||||
|
||||
const styles = stylex.create({
|
||||
note: {
|
||||
marginTop: "0.75rem",
|
||||
fontSize: "0.875rem",
|
||||
lineHeight: "1.25rem",
|
||||
color: colors.textMuted,
|
||||
},
|
||||
root: {
|
||||
marginTop: "0.75rem",
|
||||
},
|
||||
list: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "0.25rem",
|
||||
},
|
||||
checkboxLabel: {
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
gap: "0.5rem",
|
||||
fontSize: "0.875rem",
|
||||
lineHeight: "1.25rem",
|
||||
},
|
||||
buttonRow: {
|
||||
marginTop: "0.75rem",
|
||||
display: "flex",
|
||||
gap: "0.5rem",
|
||||
},
|
||||
});
|
||||
|
||||
export default function GroupSourcesEditor({ groupId, blocklists }: Props) {
|
||||
const queryClient = useQueryClient();
|
||||
const sources = useQuery(groupSourcesQuery(groupId));
|
||||
@@ -21,7 +52,7 @@ export default function GroupSourcesEditor({ groupId, blocklists }: Props) {
|
||||
|
||||
if (sources.isPending) {
|
||||
return (
|
||||
<p role="status" className="mt-3 text-sm text-zinc-500">
|
||||
<p role="status" {...stylex.props(styles.note)}>
|
||||
Loading sources…
|
||||
</p>
|
||||
);
|
||||
@@ -29,27 +60,23 @@ export default function GroupSourcesEditor({ groupId, blocklists }: Props) {
|
||||
if (sources.isError) return <InlineError error={sources.error} />;
|
||||
|
||||
if (blocklists.length === 0) {
|
||||
return (
|
||||
<p className="mt-3 text-sm text-zinc-500">
|
||||
No blocklist sources exist yet — add them on the Blocklists page.
|
||||
</p>
|
||||
);
|
||||
return <p {...stylex.props(styles.note)}>No blocklist sources exist yet — add them on the Blocklists page.</p>;
|
||||
}
|
||||
|
||||
const current = selected ?? sources.data;
|
||||
const dirty = !sameSet(current, sources.data);
|
||||
|
||||
return (
|
||||
<div className="mt-3">
|
||||
<ul className="space-y-1">
|
||||
<div {...stylex.props(styles.root)}>
|
||||
<ul {...stylex.props(styles.list)}>
|
||||
{blocklists.map((blocklist) => (
|
||||
<li key={blocklist.id}>
|
||||
<label className="inline-flex items-center gap-2 text-sm">
|
||||
<label {...stylex.props(styles.checkboxLabel)}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={current.includes(blocklist.id)}
|
||||
onChange={() => setSelected(toggleSource(current, blocklist.id))}
|
||||
className={focusRing}
|
||||
{...stylex.props(shared.focusRing)}
|
||||
/>
|
||||
{blocklist.name}
|
||||
</label>
|
||||
@@ -57,7 +84,7 @@ export default function GroupSourcesEditor({ groupId, blocklists }: Props) {
|
||||
))}
|
||||
</ul>
|
||||
<InlineError error={mutation.error} />
|
||||
<div className="mt-3 flex gap-2">
|
||||
<div {...stylex.props(styles.buttonRow)}>
|
||||
<button
|
||||
type="button"
|
||||
disabled={!dirty || mutation.isPending || readOnly}
|
||||
@@ -65,12 +92,16 @@ export default function GroupSourcesEditor({ groupId, blocklists }: Props) {
|
||||
onClick={() =>
|
||||
mutation.mutate({ id: groupId, sourceIds: current }, { onSuccess: () => setSelected(null) })
|
||||
}
|
||||
className={primaryButtonClass}
|
||||
{...stylex.props(shared.primaryButton, shared.focusRing)}
|
||||
>
|
||||
Save sources
|
||||
</button>
|
||||
{dirty && (
|
||||
<button type="button" onClick={() => setSelected(null)} className={buttonClass}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSelected(null)}
|
||||
{...stylex.props(shared.button, shared.focusRing)}
|
||||
>
|
||||
Discard
|
||||
</button>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user