style: tighten household settings layout
This commit is contained in:
parent
74913c3435
commit
043460ac21
@ -28,6 +28,20 @@ const JOIN_POLICY_OPTIONS = [
|
||||
{ label: "Manual", value: "APPROVAL_REQUIRED" },
|
||||
];
|
||||
|
||||
const ROLE_METADATA = {
|
||||
owner: { icon: "👑", label: "Owner" },
|
||||
admin: { icon: "🛠️", label: "Admin" },
|
||||
member: { icon: "🙂", label: "Member" },
|
||||
viewer: { icon: "👀", label: "Viewer" },
|
||||
};
|
||||
|
||||
const STATUS_METADATA = {
|
||||
Active: { tone: "active", icon: "🟢" },
|
||||
Used: { tone: "used", icon: "⚪" },
|
||||
Revoked: { tone: "revoked", icon: "🔴" },
|
||||
Expired: { tone: "expired", icon: "🟠" },
|
||||
};
|
||||
|
||||
export default function ManageHousehold() {
|
||||
const { userId } = useContext(AuthContext);
|
||||
const { activeHousehold, refreshHouseholds } = useContext(HouseholdContext);
|
||||
@ -309,10 +323,21 @@ export default function ManageHousehold() {
|
||||
);
|
||||
};
|
||||
|
||||
const managerCount = members.filter((member) => ["owner", "admin"].includes(member.role)).length;
|
||||
const memberCount = members.filter((member) => member.role === "member").length;
|
||||
|
||||
return (
|
||||
<div className="manage-household">
|
||||
<section key="household-name" className="manage-section">
|
||||
<h2>Household Name</h2>
|
||||
<div className="manage-section-header">
|
||||
<div>
|
||||
<p className="manage-section-eyebrow">Household</p>
|
||||
<h2>Identity</h2>
|
||||
<p className="section-description">
|
||||
Keep the household name crisp and easy to recognize across invites and shared lists.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{editingName ? (
|
||||
<div className="edit-name-form">
|
||||
<input
|
||||
@ -327,7 +352,14 @@ export default function ManageHousehold() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="name-display">
|
||||
<div className="name-display-copy">
|
||||
<h3>{activeHousehold.name}</h3>
|
||||
<div className="household-summary-chips">
|
||||
<span className="household-summary-chip">🏠 {members.length} people</span>
|
||||
<span className="household-summary-chip">🛡️ {managerCount} managers</span>
|
||||
<span className="household-summary-chip">🛒 {memberCount} shoppers</span>
|
||||
</div>
|
||||
</div>
|
||||
{isManager && (
|
||||
<button
|
||||
onClick={() => {
|
||||
@ -345,30 +377,48 @@ export default function ManageHousehold() {
|
||||
|
||||
{isManager && (
|
||||
<section key="invite-code" className="manage-section">
|
||||
<h2>Legacy Invite Code</h2>
|
||||
<div className="manage-section-header">
|
||||
<div>
|
||||
<p className="manage-section-eyebrow">Legacy Access</p>
|
||||
<h2>Invite Code</h2>
|
||||
<p className="section-description">
|
||||
Share this code for legacy join-by-code flows.
|
||||
Keep a simple code handy for older join flows while newer invite links stay fully managed below.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="invite-actions">
|
||||
<div className="invite-code-panel">
|
||||
<div className="invite-code-copy">
|
||||
<span className="invite-code-label">Current code</span>
|
||||
<code className="invite-code">{showInviteCode ? activeHousehold.invite_code : "••••••••"}</code>
|
||||
</div>
|
||||
<div className="invite-action-group">
|
||||
<button onClick={() => setShowInviteCode(!showInviteCode)} className="btn-secondary">
|
||||
{showInviteCode ? "Hide Code" : "Show Code"}
|
||||
</button>
|
||||
{showInviteCode && (
|
||||
<React.Fragment key="invite-code-display">
|
||||
<code className="invite-code">{activeHousehold.invite_code}</code>
|
||||
<button onClick={copyInviteCode} className="btn-secondary">Copy</button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
<button onClick={copyInviteCode} className="btn-secondary" disabled={!showInviteCode}>
|
||||
Copy
|
||||
</button>
|
||||
<button onClick={handleRefreshInvite} className="btn-secondary">
|
||||
Generate New Code
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{isManager && (
|
||||
<section key="join-and-invites" className="manage-section">
|
||||
<div className="manage-section-header">
|
||||
<div>
|
||||
<p className="manage-section-eyebrow">Entry Rules</p>
|
||||
<h2>Join and Invites</h2>
|
||||
<p className="section-description">
|
||||
Decide how new people can enter, then generate compact links that match your current policy.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{inviteError && <p className="section-error">{inviteError}</p>}
|
||||
|
||||
<ToggleButtonGroup
|
||||
@ -384,7 +434,7 @@ export default function ManageHousehold() {
|
||||
|
||||
<div className="invite-controls">
|
||||
<label>
|
||||
TTL
|
||||
<span className="invite-control-label">TTL</span>
|
||||
<select value={ttlDays} onChange={(e) => setTtlDays(Number(e.target.value))}>
|
||||
{[1, 2, 3, 4, 5, 6, 7].map((day) => (
|
||||
<option key={day} value={day}>{day} day{day > 1 ? "s" : ""}</option>
|
||||
@ -392,7 +442,7 @@ export default function ManageHousehold() {
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
Usage
|
||||
<span className="invite-control-label">Usage</span>
|
||||
<select value={singleUseMode} onChange={(e) => setSingleUseMode(e.target.value)}>
|
||||
<option value="UNLIMITED">Unlimited</option>
|
||||
<option value="ONE_TIME">1 use</option>
|
||||
@ -412,12 +462,18 @@ export default function ManageHousehold() {
|
||||
{inviteLinks.map((link) => {
|
||||
const status = getLinkStatus(link);
|
||||
const isActive = status === "Active";
|
||||
const statusMeta = STATUS_METADATA[status] || STATUS_METADATA.Active;
|
||||
return (
|
||||
<div key={link.id} className="invite-link-card">
|
||||
<div>
|
||||
<p className="invite-link-token">Token ending in {String(link.token).slice(-4)}</p>
|
||||
<div className="invite-link-main">
|
||||
<div className="invite-link-topline">
|
||||
<p className="invite-link-token">Invite ending in {String(link.token).slice(-4)}</p>
|
||||
<span className={`invite-status-badge is-${statusMeta.tone}`}>
|
||||
{statusMeta.icon} {status}
|
||||
</span>
|
||||
</div>
|
||||
<p className="invite-link-meta">
|
||||
Status: <strong>{status}</strong> | Policy: {link.policy} | TTL: until {new Date(link.expires_at).toLocaleString()}
|
||||
Policy: {link.policy} • Expires {new Date(link.expires_at).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
<div className="invite-link-actions">
|
||||
@ -446,20 +502,37 @@ export default function ManageHousehold() {
|
||||
)}
|
||||
|
||||
<section key="members" className="manage-section">
|
||||
<div className="manage-section-header">
|
||||
<div>
|
||||
<p className="manage-section-eyebrow">People</p>
|
||||
<h2>Members ({members.length})</h2>
|
||||
<p className="section-description">
|
||||
Role badges and compact actions make it easier to see who runs the household and who just shops.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{loading ? (
|
||||
<p>Loading members...</p>
|
||||
) : (
|
||||
<div className="members-list">
|
||||
{members.map((member) => (
|
||||
{members.map((member) => {
|
||||
const roleMeta = ROLE_METADATA[member.role] || { icon: "👤", label: member.role };
|
||||
const isSelf = member.id === parseInt(userId, 10);
|
||||
|
||||
return (
|
||||
<div key={member.id} className="member-card">
|
||||
<div className="member-avatar" aria-hidden="true">{roleMeta.icon}</div>
|
||||
<div className="member-info">
|
||||
<span className="member-role">{member.role}</span>
|
||||
<span className="member-name">
|
||||
{member.username} [{member.id}] {member.id === parseInt(userId, 10) ? "(You)" : ""}
|
||||
<div className="member-topline">
|
||||
<span className={`member-role member-role-${member.role}`}>
|
||||
{roleMeta.icon} {roleMeta.label}
|
||||
</span>
|
||||
{isSelf && <span className="member-self-pill">✨ You</span>}
|
||||
</div>
|
||||
{isManager && member.id !== parseInt(userId, 10) && member.role !== "owner" && (
|
||||
<span className="member-name">{member.username}</span>
|
||||
<span className="member-meta">ID #{member.id}</span>
|
||||
</div>
|
||||
{isManager && !isSelf && member.role !== "owner" && (
|
||||
<div className="member-actions">
|
||||
<button
|
||||
onClick={() => handleUpdateRole(member.id, member.role, member.username)}
|
||||
@ -476,19 +549,24 @@ export default function ManageHousehold() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{(isManager || isMemberOnly) && (
|
||||
<section key="danger-zone" className="manage-section danger-zone">
|
||||
<div className="manage-section-header">
|
||||
<div>
|
||||
<p className="manage-section-eyebrow">Final Actions</p>
|
||||
<h2>Danger Zone</h2>
|
||||
<p className="section-description">
|
||||
{isMemberOnly
|
||||
? "Leaving removes your access to this household."
|
||||
: "Deleting a household is permanent and will delete all lists, items, and history."}
|
||||
</p>
|
||||
</div>
|
||||
{isMemberOnly ? (
|
||||
<button onClick={() => setIsLeaveModalOpen(true)} className="btn-danger">
|
||||
Leave Household
|
||||
@ -498,6 +576,7 @@ export default function ManageHousehold() {
|
||||
Delete Household
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
|
||||
@ -2,65 +2,117 @@
|
||||
.manage-household {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
max-width: 800px;
|
||||
gap: 1rem;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Section Styling */
|
||||
.manage-section {
|
||||
background: var(--card-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 1.2rem 1.25rem;
|
||||
border: 1px solid var(--color-border-light);
|
||||
border-radius: var(--border-radius-lg);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(255, 255, 255, 0.72)),
|
||||
var(--card-bg);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.manage-section h2 {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
.manage-section-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.manage-section-header h2 {
|
||||
margin: 0.15rem 0 0;
|
||||
font-size: 1.2rem;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.manage-section-eyebrow {
|
||||
margin: 0;
|
||||
color: var(--primary);
|
||||
font-size: 0.74rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.section-description {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 0.92rem;
|
||||
line-height: 1.55;
|
||||
margin: 0.45rem 0 0;
|
||||
}
|
||||
|
||||
.section-error {
|
||||
color: var(--danger);
|
||||
margin: 0;
|
||||
padding: 0.8rem 0.95rem;
|
||||
border-radius: var(--border-radius-md);
|
||||
border: 1px solid color-mix(in srgb, var(--danger) 28%, transparent);
|
||||
background: color-mix(in srgb, var(--danger-light) 78%, white);
|
||||
}
|
||||
|
||||
/* Household Name Section */
|
||||
.name-display {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.name-display-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.7rem;
|
||||
}
|
||||
|
||||
.name-display h3 {
|
||||
font-size: 1.5rem;
|
||||
font-size: 1.55rem;
|
||||
color: var(--text-primary);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.edit-name-form {
|
||||
.household-summary-chips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.household-summary-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
padding: 0.4rem 0.75rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
background: var(--primary-light);
|
||||
color: var(--primary-dark);
|
||||
font-size: 0.82rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.edit-name-form {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||
gap: 0.75rem;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.edit-name-form input {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
padding: 0.75rem;
|
||||
min-width: 0;
|
||||
padding: 0.85rem 1rem;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
font-size: 1rem;
|
||||
background: var(--background);
|
||||
border-radius: var(--border-radius-md);
|
||||
font-size: 0.98rem;
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
@ -68,73 +120,121 @@
|
||||
.invite-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.invite-code-panel {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 0.9rem;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 0.95rem 1rem;
|
||||
border: 1px solid var(--color-border-light);
|
||||
border-radius: var(--border-radius-lg);
|
||||
background: rgba(255, 255, 255, 0.58);
|
||||
}
|
||||
|
||||
.invite-code-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.invite-code-label {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.invite-code {
|
||||
display: inline-flex;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
background: var(--background);
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 6px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 1rem;
|
||||
padding: 0.65rem 0.8rem;
|
||||
border-radius: var(--border-radius-md);
|
||||
font-family: var(--font-family-mono);
|
||||
font-size: 0.95rem;
|
||||
color: var(--primary);
|
||||
border: 2px solid var(--border);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
border: 1px solid var(--border);
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.section-error {
|
||||
color: var(--danger);
|
||||
margin: 0 0 0.75rem 0;
|
||||
.invite-action-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.55rem;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.manage-household-join-policy-toggle {
|
||||
margin-bottom: 1rem;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.invite-controls {
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(140px, 180px)) auto;
|
||||
gap: 0.8rem;
|
||||
align-items: end;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.invite-controls label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
gap: 0.35rem;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.invite-control-label {
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
color: var(--text-secondary);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.invite-controls select {
|
||||
min-width: 120px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 0.45rem 0.6rem;
|
||||
background: var(--background);
|
||||
border-radius: var(--border-radius-md);
|
||||
padding: 0.7rem 0.75rem;
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.invite-links-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.8rem;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.invite-link-card {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 0.85rem;
|
||||
align-items: center;
|
||||
padding: 0.9rem 1rem;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--background);
|
||||
border-radius: 8px;
|
||||
padding: 0.9rem;
|
||||
border-radius: var(--border-radius-lg);
|
||||
background: rgba(255, 255, 255, 0.62);
|
||||
}
|
||||
|
||||
.invite-link-main {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.invite-link-topline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.75rem;
|
||||
gap: 0.6rem;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
|
||||
.invite-link-token,
|
||||
@ -143,118 +243,193 @@
|
||||
}
|
||||
|
||||
.invite-link-token {
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.invite-link-meta {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.84rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.invite-status-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
padding: 0.28rem 0.6rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.invite-status-badge.is-active {
|
||||
background: var(--success-light);
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.invite-status-badge.is-used {
|
||||
background: color-mix(in srgb, var(--color-gray-200) 74%, white);
|
||||
color: var(--color-gray-700);
|
||||
}
|
||||
|
||||
.invite-status-badge.is-revoked {
|
||||
background: var(--danger-light);
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.invite-status-badge.is-expired {
|
||||
background: var(--color-warning-light);
|
||||
color: var(--color-warning);
|
||||
}
|
||||
|
||||
.invite-link-actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* Members Section */
|
||||
.members-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
|
||||
gap: 0.85rem;
|
||||
}
|
||||
|
||||
.member-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1.25rem;
|
||||
background: var(--background);
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
gap: 0.85rem;
|
||||
align-items: flex-start;
|
||||
padding: 0.95rem 1rem;
|
||||
background: rgba(255, 255, 255, 0.62);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
border-radius: var(--border-radius-lg);
|
||||
transition: all 0.2s;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.member-card:hover {
|
||||
background: var(--card-hover);
|
||||
border-color: var(--primary);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.member-avatar {
|
||||
width: 2.6rem;
|
||||
height: 2.6rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 999px;
|
||||
background: var(--primary-light);
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.member-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
gap: 0.35rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.member-topline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.member-name {
|
||||
font-weight: 500;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.member-meta {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.member-role {
|
||||
font-size: 0.85rem;
|
||||
padding: 0.2rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
font-size: 0.78rem;
|
||||
padding: 0.24rem 0.55rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
width: fit-content;
|
||||
text-transform: capitalize;
|
||||
background: var(--primary-light, rgba(0, 122, 255, 0.1));
|
||||
color: var(--primary);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.member-role-owner {
|
||||
background: rgba(245, 158, 11, 0.18);
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
.member-role-admin {
|
||||
background: rgba(30, 144, 255, 0.16);
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.member-role-member,
|
||||
.member-role-viewer {
|
||||
background: rgba(139, 92, 246, 0.12);
|
||||
color: #6d28d9;
|
||||
}
|
||||
|
||||
.member-self-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.24rem 0.5rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
background: rgba(245, 158, 11, 0.16);
|
||||
color: #a16207;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.member-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
gap: 0.55rem;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 0.4rem;
|
||||
}
|
||||
|
||||
/* Danger Zone */
|
||||
.danger-zone {
|
||||
border-color: var(--danger);
|
||||
border-color: color-mix(in srgb, var(--danger) 30%, transparent);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(254, 242, 242, 0.95), rgba(255, 255, 255, 0.78)),
|
||||
var(--card-bg);
|
||||
}
|
||||
|
||||
.danger-zone h2 {
|
||||
.danger-zone h2,
|
||||
.danger-zone .manage-section-eyebrow {
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.danger-zone .manage-section-header {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn-primary,
|
||||
.btn-secondary,
|
||||
.btn-danger {
|
||||
padding: 0.5rem 1rem;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary,
|
||||
.btn-secondary {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover,
|
||||
.btn-secondary:hover {
|
||||
background: var(--primary-dark, #0056b3);
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: var(--danger);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background: var(--danger-dark, #c82333);
|
||||
min-height: 40px;
|
||||
padding: 0.58rem 0.95rem;
|
||||
border-radius: var(--border-radius-full);
|
||||
font-size: 0.88rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
padding: 0.4rem 0.75rem;
|
||||
font-size: 0.85rem;
|
||||
min-height: 34px;
|
||||
padding: 0.38rem 0.72rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.btn-danger:disabled {
|
||||
@ -264,62 +439,54 @@
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.manage-section {
|
||||
padding: 1.25rem;
|
||||
@media (max-width: 900px) {
|
||||
.invite-controls {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.name-display {
|
||||
.invite-controls .btn-primary {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.invite-link-card {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.invite-link-actions {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.manage-section {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.manage-section-header,
|
||||
.name-display,
|
||||
.danger-zone .manage-section-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.edit-name-form {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
align-items: stretch;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.edit-name-form input {
|
||||
width: 100%;
|
||||
min-width: unset;
|
||||
.invite-code-panel {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.edit-name-form button {
|
||||
width: 100%;
|
||||
.invite-action-group {
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
.member-card {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.member-actions {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.member-actions button {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.invite-actions {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.invite-actions button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.invite-code {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
.invite-action-group button {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
.invite-controls {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.invite-controls label,
|
||||
@ -328,11 +495,19 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.invite-link-actions {
|
||||
.members-list {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.member-card {
|
||||
grid-template-columns: auto 1fr;
|
||||
}
|
||||
|
||||
.member-actions {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.invite-link-actions button {
|
||||
flex: 1;
|
||||
.member-actions button {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user