Polish dashboard page chrome and user access UI.
Rename Customers to Users with FA/EN titles, compact headers and filter bars across apps, and refine manager role copy plus a customer-header link to the business dashboard. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
beec3035e5
commit
6c52ce1247
@@ -6,7 +6,7 @@
|
||||
|
||||
.roleOption {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 10px;
|
||||
@@ -16,17 +16,37 @@
|
||||
font-family: var(--font-ui);
|
||||
}
|
||||
|
||||
.roleOption input[type='radio'] {
|
||||
accent-color: var(--primary);
|
||||
margin-top: 2px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.roleOption:has(input:checked) {
|
||||
border-color: rgba(var(--primary-rgb) / 0.35);
|
||||
background: rgba(var(--primary-rgb) / 0.08);
|
||||
}
|
||||
|
||||
.roleOptionText {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.roleOptionLabel {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.roleOptionDesc {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.roleHint {
|
||||
margin: 12px 0 8px;
|
||||
font-size: 12px;
|
||||
@@ -36,12 +56,25 @@
|
||||
}
|
||||
|
||||
.roleListNested {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
margin-inline-start: 12px;
|
||||
padding-inline-start: 10px;
|
||||
border-inline-start: 2px solid rgba(var(--primary-rgb) / 0.2);
|
||||
}
|
||||
|
||||
@media (min-width: 560px) {
|
||||
.roleListNested {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.roleListNested .roleOption:last-child:nth-child(odd) {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.roleBadge {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
|
||||
@@ -23,6 +23,12 @@ const TEAM_ROLE_LABEL_KEYS: Record<(typeof ALL_TEAM_ROLES)[number], BusinessMess
|
||||
viewer: 'customers.access.role.viewer',
|
||||
}
|
||||
|
||||
const TEAM_ROLE_DESC_KEYS: Record<(typeof ALL_TEAM_ROLES)[number], BusinessMessageKey> = {
|
||||
admin: 'customers.access.role.admin.desc',
|
||||
editor: 'customers.access.role.editor.desc',
|
||||
viewer: 'customers.access.role.viewer.desc',
|
||||
}
|
||||
|
||||
export interface ChangeUserAccessModalProps {
|
||||
open: boolean
|
||||
user: BusinessCustomerListItem | null
|
||||
@@ -185,27 +191,33 @@ export function ChangeUserAccessModal({
|
||||
|
||||
{access === 'staff' ? (
|
||||
<>
|
||||
<p className={styles.roleHint}>
|
||||
{canAssignAdmin
|
||||
? t('customers.access.hintSuperAdmin')
|
||||
: t('customers.access.hintBusiness')}
|
||||
</p>
|
||||
{!canAssignAdmin ? (
|
||||
<p className={styles.roleHint}>{t('customers.access.hintBusiness')}</p>
|
||||
) : null}
|
||||
<div className={`${styles.roleList} ${styles.roleListNested}`}>
|
||||
{teamRoles.map((slug) => (
|
||||
<label key={slug} className={styles.roleOption}>
|
||||
<input
|
||||
type="radio"
|
||||
name="team-role"
|
||||
value={slug}
|
||||
checked={teamRole === slug}
|
||||
onChange={() => setTeamRole(slug)}
|
||||
disabled={submitting}
|
||||
/>
|
||||
<span className={styles.roleOptionLabel}>
|
||||
{t(TEAM_ROLE_LABEL_KEYS[slug as (typeof ALL_TEAM_ROLES)[number]])}
|
||||
</span>
|
||||
</label>
|
||||
))}
|
||||
{teamRoles.map((slug) => {
|
||||
const role = slug as (typeof ALL_TEAM_ROLES)[number]
|
||||
return (
|
||||
<label key={slug} className={styles.roleOption}>
|
||||
<input
|
||||
type="radio"
|
||||
name="team-role"
|
||||
value={slug}
|
||||
checked={teamRole === slug}
|
||||
onChange={() => setTeamRole(slug)}
|
||||
disabled={submitting}
|
||||
/>
|
||||
<span className={styles.roleOptionText}>
|
||||
<span className={styles.roleOptionLabel}>
|
||||
{t(TEAM_ROLE_LABEL_KEYS[role])}
|
||||
</span>
|
||||
<span className={styles.roleOptionDesc}>
|
||||
{t(TEAM_ROLE_DESC_KEYS[role])}
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
@@ -10,10 +10,7 @@
|
||||
}
|
||||
|
||||
.filtersTitle {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 8px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.filtersGrid {
|
||||
|
||||
@@ -8,14 +8,33 @@
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
margin-bottom: 36px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.pageTitle {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
gap: 0.15em 0.4em;
|
||||
}
|
||||
|
||||
.pageTitleEn {
|
||||
font-size: 0.52em;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-muted);
|
||||
font-family: var(--font-en), var(--font-ui);
|
||||
}
|
||||
|
||||
.pageTitleEn::before {
|
||||
content: '•';
|
||||
margin-inline-end: 0.4em;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.welcomeTitle {
|
||||
@@ -26,8 +45,14 @@
|
||||
}
|
||||
|
||||
.pageSubtitle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pageSubtitleContent {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.welcomeSubtitle {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { useLocale } from '@meshkee/dashboard-ui'
|
||||
import type { ReactNode } from 'react'
|
||||
import pageStyles from './PageContent.module.css'
|
||||
|
||||
interface PageTitleProps {
|
||||
children: ReactNode
|
||||
/** English accent shown after a bullet in FA locale (e.g. USERS). */
|
||||
en?: string
|
||||
}
|
||||
|
||||
export function PageTitle({ children, en }: PageTitleProps) {
|
||||
const { locale } = useLocale()
|
||||
return (
|
||||
<h2 className={pageStyles.pageTitle}>
|
||||
{children}
|
||||
{en && locale === 'fa' ? <span className={pageStyles.pageTitleEn}>{en}</span> : null}
|
||||
</h2>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user