button theme changed

This commit is contained in:
suryacp23 2026-07-21 16:03:37 +05:30
parent 6bb5b6e18a
commit 7a832325f3
13 changed files with 104 additions and 41 deletions

View File

@ -103,6 +103,9 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId:
setValues(defaultValues); setValues(defaultValues);
setLoading(false); setLoading(false);
if (res.activity_name) {
onActivityChange?.(res.activity_name);
}
} }
}) })
.catch((err: any) => { .catch((err: any) => {
@ -161,7 +164,10 @@ export function DynamicForm({ client, activityId: initialActivityId, instanceId:
}; };
if (loading) { if (loading) {
return <div className="p-8 flex justify-center"><Spinner label="Loading form..." /></div>; const formattedActivity = currentActivityId
? currentActivityId.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')
: 'form';
return <div className="p-8 flex justify-center"><Spinner label={`Loading ${formattedActivity}...`} /></div>;
} }
if (error || !schema) { if (error || !schema) {
return <div className="p-4 text-ruby-600">Failed to load form: {error}</div>; return <div className="p-4 text-ruby-600">Failed to load form: {error}</div>;

View File

@ -73,7 +73,7 @@ export function WfLookupField({ label, required, value, onChange, client, config
return ( return (
<SelectField <SelectField
label={loading ? `${label} (Loading...)` : label} label={label}
required={required} required={required}
value={String(value || '')} value={String(value || '')}
onChange={onChange} onChange={onChange}

View File

@ -28,7 +28,7 @@ export function Input({
return ( return (
<label className={cn('flex flex-col gap-1.5 font-sans', disabled && 'cursor-not-allowed', className)}> <label className={cn('flex flex-col gap-1.5 font-sans', disabled && 'cursor-not-allowed', className)}>
{label && ( {label && (
<span className="text-sm font-medium text-muted"> <span className="text-sm font-bold text-slate-700">
{label} {label}
{required && <span className="text-ruby-600"> *</span>} {required && <span className="text-ruby-600"> *</span>}
</span> </span>

View File

@ -21,7 +21,7 @@ export function Select({ label, hint, options = [], required, className, ...rest
return ( return (
<label className={cn('flex flex-col gap-1.5 font-sans', className)}> <label className={cn('flex flex-col gap-1.5 font-sans', className)}>
{label && ( {label && (
<span className="text-sm font-medium text-muted"> <span className="text-sm font-bold text-slate-700">
{label} {label}
{required && <span className="text-ruby-600"> *</span>} {required && <span className="text-ruby-600"> *</span>}
</span> </span>

View File

@ -20,7 +20,7 @@ export function Textarea({
return ( return (
<label className={cn('flex flex-col gap-1.5 font-sans', disabled && 'cursor-not-allowed', className)}> <label className={cn('flex flex-col gap-1.5 font-sans', disabled && 'cursor-not-allowed', className)}>
{label && ( {label && (
<span className="text-sm font-medium text-muted"> <span className="text-sm font-bold text-slate-700">
{label} {label}
{required && <span className="text-ruby-600"> *</span>} {required && <span className="text-ruby-600"> *</span>}
</span> </span>

View File

@ -105,10 +105,10 @@ export function RecordView({
setLoading(true); setLoading(true);
setError(null); setError(null);
try { try {
const r = await client.recordView(rvUid, { const r = await client.recordView(rvUid, {
page, page,
limit: internalPageSize, limit: internalPageSize,
search: debounced, search: debounced,
filters: filtersParam, filters: filtersParam,
sortBy, sortBy,
sortDir, sortDir,
@ -197,7 +197,7 @@ export function RecordView({
const options = resp.config.filter_options?.[key]; const options = resp.config.filter_options?.[key];
if (!options || options.length === 0) return null; if (!options || options.length === 0) return null;
const opts = options.map(o => ({ value: o, label: o })); const opts = options.map(o => ({ value: o, label: o }));
return ( return (
<Select <Select
@ -237,17 +237,17 @@ export function RecordView({
<div className="overflow-x-auto scrollbar-slim"> <div className="overflow-x-auto scrollbar-slim">
<table className="w-full border-collapse min-w-[640px]"> <table className="w-full border-collapse min-w-[640px]">
<thead> <thead>
<tr className="bg-[var(--z-rv-table-header)] border-b border-[var(--z-rv-table-border)]"> <tr className="border-b border-[var(--z-rv-table-border)]">
{fields.map((f) => ( {fields.map((f) => (
<th <th
key={f.field_key} key={f.field_key}
className="text-left px-[18px] py-[11px] text-[10px] font-bold uppercase tracking-[0.06em] text-faint whitespace-nowrap" className="text-left px-[18px] py-4 text-sm font-bold uppercase tracking-wider text-black/70 whitespace-nowrap bg-slate-50/50"
> >
{f.output_label} {f.output_label}
</th> </th>
))} ))}
{rowActions && ( {rowActions && (
<th className="sticky right-0 bg-inherit px-4 py-3 text-left text-[10px] font-bold uppercase tracking-[0.06em] text-faint border-b border-border-subtle z-10 w-24"> <th className="sticky right-0 bg-slate-50/50 px-4 py-4 text-left text-sm font-extrabold uppercase tracking-wider text-[#1b37a5] border-b border-border-subtle z-10 w-24">
Actions Actions
</th> </th>
)} )}
@ -268,7 +268,7 @@ export function RecordView({
const isSku = lowerKey === 'sku_code'; const isSku = lowerKey === 'sku_code';
const isStatus = lowerKey.includes('status') || lowerKey.includes('state'); const isStatus = lowerKey.includes('status') || lowerKey.includes('state');
const valStr = formatValue(row[f.field_key], f.field_key); const valStr = formatValue(row[f.field_key], f.field_key);
let content = <>{valStr}</>; let content = <>{valStr}</>;
if (valStr !== '—' && valStr !== '') { if (valStr !== '—' && valStr !== '') {
@ -283,7 +283,7 @@ export function RecordView({
"bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200", "bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200",
"bg-teal-50 text-teal-700 border-teal-200", "bg-teal-50 text-teal-700 border-teal-200",
]; ];
let hash = 0; let hash = 0;
for (let i = 0; i < valStr.length; i++) { for (let i = 0; i < valStr.length; i++) {
hash = valStr.charCodeAt(i) + ((hash << 5) - hash); hash = valStr.charCodeAt(i) + ((hash << 5) - hash);
@ -302,7 +302,7 @@ export function RecordView({
const isSuccess = valLower.includes('approve') || valLower.includes('complete') || valLower.includes('success') || valLower.includes('active'); const isSuccess = valLower.includes('approve') || valLower.includes('complete') || valLower.includes('success') || valLower.includes('active');
const isWarning = valLower.includes('pending') || valLower.includes('draft') || valLower.includes('hold'); const isWarning = valLower.includes('pending') || valLower.includes('draft') || valLower.includes('hold');
const isDanger = valLower.includes('reject') || valLower.includes('fail') || valLower.includes('cancel'); const isDanger = valLower.includes('reject') || valLower.includes('fail') || valLower.includes('cancel');
if (isSuccess) colorClass = "bg-emerald-50 text-emerald-700 border-emerald-200"; if (isSuccess) colorClass = "bg-emerald-50 text-emerald-700 border-emerald-200";
else if (isWarning) colorClass = "bg-amber-50 text-amber-700 border-amber-200"; else if (isWarning) colorClass = "bg-amber-50 text-amber-700 border-amber-200";
else if (isDanger) colorClass = "bg-red-50 text-red-700 border-red-200"; else if (isDanger) colorClass = "bg-red-50 text-red-700 border-red-200";
@ -317,13 +317,13 @@ export function RecordView({
} }
return ( return (
<td key={f.field_key} className="px-[18px] py-3 text-sm text-body whitespace-nowrap"> <td key={f.field_key} className="px-[18px] py-4 text-sm text-body whitespace-nowrap">
{content} {content}
</td> </td>
); );
})} })}
{rowActions && ( {rowActions && (
<td className="sticky right-0 bg-inherit px-4 py-3 whitespace-nowrap border-b border-border-subtle z-10"> <td className="sticky right-0 bg-inherit px-4 py-4 whitespace-nowrap border-b border-border-subtle z-10">
<div onClick={(e) => e.stopPropagation()}> <div onClick={(e) => e.stopPropagation()}>
{rowActions(row)} {rowActions(row)}
</div> </div>
@ -335,11 +335,11 @@ export function RecordView({
</table> </table>
</div> </div>
)} )}
<Pagination <Pagination
page={page} page={page}
pageSize={internalPageSize} pageSize={internalPageSize}
total={total} total={total}
onPage={setPage} onPage={setPage}
onPageSizeChange={(sz) => { onPageSizeChange={(sz) => {
setInternalPageSize(sz); setInternalPageSize(sz);
setPage(1); setPage(1);

View File

@ -75,8 +75,12 @@ export function formatValue(value: unknown, fieldKey?: string): string {
} }
} }
/** Number with Indian-locale grouping; falls back to the raw string. */
export function formatNumber(value: unknown): string { export function formatNumber(value: unknown): string {
const n = typeof value === 'number' ? value : Number(value); const n = typeof value === 'number' ? value : Number(value);
return Number.isFinite(n) ? n.toLocaleString('en-IN') : formatValue(value); return Number.isFinite(n) ? n.toLocaleString('en-IN') : formatValue(value);
} }
export function formatActivityName(activityId: string): string {
if (!activityId) return '';
return activityId.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
}

View File

@ -6,6 +6,7 @@ import { useEffect, useState } from 'react';
import { Button } from '../components/buttons/Button'; import { Button } from '../components/buttons/Button';
import { Plus } from 'lucide-react'; import { Plus } from 'lucide-react';
import { DynamicForm } from '../components/forms/DynamicForm'; import { DynamicForm } from '../components/forms/DynamicForm';
import { formatActivityName } from '../lib/format';
import { ORDER_BOOKING } from '../api/config'; import { ORDER_BOOKING } from '../api/config';
import { orderBookingClient } from '../api/clients'; import { orderBookingClient } from '../api/clients';
@ -14,6 +15,7 @@ export function CallsPage() {
const instanceId = params.instanceId ? Number(params.instanceId) : undefined; const instanceId = params.instanceId ? Number(params.instanceId) : undefined;
const navigate = useNavigate(); const navigate = useNavigate();
const [isCreating, setIsCreating] = useState(false); const [isCreating, setIsCreating] = useState(false);
const [createTitle, setCreateTitle] = useState(formatActivityName(ORDER_BOOKING.activities.LOG_VISIT.uid));
const [refreshKey, setRefreshKey] = useState(0); const [refreshKey, setRefreshKey] = useState(0);
const [activeActivity, setActiveActivity] = useState<{ id: string; name: string } | null>(null); const [activeActivity, setActiveActivity] = useState<{ id: string; name: string } | null>(null);
@ -89,7 +91,10 @@ export function CallsPage() {
if (id != null) navigate(`/calls/${id}`); if (id != null) navigate(`/calls/${id}`);
}} }}
headerActions={ headerActions={
<Button size="sm" iconLeft={<Plus size={14} />} onClick={() => setIsCreating(true)}> <Button size="sm" iconLeft={<Plus size={14} />} onClick={() => {
setCreateTitle(formatActivityName(ORDER_BOOKING.activities.LOG_VISIT.uid));
setIsCreating(true);
}}>
Log Visit Log Visit
</Button> </Button>
} }
@ -98,7 +103,7 @@ export function CallsPage() {
<Modal <Modal
open={isCreating} open={isCreating}
onClose={() => setIsCreating(false)} onClose={() => setIsCreating(false)}
title="Log Visit" title={createTitle}
width="md" width="md"
> >
<DynamicForm <DynamicForm
@ -109,6 +114,7 @@ export function CallsPage() {
setRefreshKey(k => k + 1); setRefreshKey(k => k + 1);
}} }}
onCancel={() => setIsCreating(false)} onCancel={() => setIsCreating(false)}
onActivityChange={setCreateTitle}
/> />
</Modal> </Modal>

View File

@ -6,6 +6,7 @@ import { useState } from 'react';
import { Button } from '../components/buttons/Button'; import { Button } from '../components/buttons/Button';
import { Plus } from 'lucide-react'; import { Plus } from 'lucide-react';
import { DynamicForm } from '../components/forms/DynamicForm'; import { DynamicForm } from '../components/forms/DynamicForm';
import { formatActivityName } from '../lib/format';
import { DAILY_REPORTS } from '../api/config'; import { DAILY_REPORTS } from '../api/config';
import { dailyReportsClient } from '../api/clients'; import { dailyReportsClient } from '../api/clients';
@ -14,7 +15,9 @@ export function DailyLogsPage() {
const instanceId = params.instanceId ? Number(params.instanceId) : undefined; const instanceId = params.instanceId ? Number(params.instanceId) : undefined;
const navigate = useNavigate(); const navigate = useNavigate();
const [isCreating, setIsCreating] = useState(false); const [isCreating, setIsCreating] = useState(false);
const [createTitle, setCreateTitle] = useState(formatActivityName(DAILY_REPORTS.activities.INIT.uid));
const [punchOutInstanceId, setPunchOutInstanceId] = useState<number | string | null>(null); const [punchOutInstanceId, setPunchOutInstanceId] = useState<number | string | null>(null);
const [punchOutTitle, setPunchOutTitle] = useState(formatActivityName(DAILY_REPORTS.activities.PUNCH_OUT.uid));
const [refreshKey, setRefreshKey] = useState(0); const [refreshKey, setRefreshKey] = useState(0);
return ( return (
@ -27,7 +30,10 @@ export function DailyLogsPage() {
if (id != null) navigate(`/daily/${id}`); if (id != null) navigate(`/daily/${id}`);
}} }}
headerActions={ headerActions={
<Button size="sm" iconLeft={<Plus size={14} />} onClick={() => setIsCreating(true)}> <Button size="sm" iconLeft={<Plus size={14} />} onClick={() => {
setCreateTitle(formatActivityName(DAILY_REPORTS.activities.INIT.uid));
setIsCreating(true);
}}>
Punch In Punch In
</Button> </Button>
} }
@ -37,7 +43,10 @@ export function DailyLogsPage() {
if (state.includes('out') || !state.includes('in')) return null; if (state.includes('out') || !state.includes('in')) return null;
return ( return (
<Button size="sm" variant="secondary" onClick={() => setPunchOutInstanceId(row.instance_id as string | number)}> <Button size="sm" variant="secondary" onClick={() => {
setPunchOutTitle(formatActivityName(DAILY_REPORTS.activities.PUNCH_OUT.uid));
setPunchOutInstanceId(row.instance_id as string | number);
}}>
Punch Out Punch Out
</Button> </Button>
); );
@ -47,7 +56,7 @@ export function DailyLogsPage() {
<Modal <Modal
open={isCreating} open={isCreating}
onClose={() => setIsCreating(false)} onClose={() => setIsCreating(false)}
title="Punch In" title={createTitle}
width="md" width="md"
> >
<DynamicForm <DynamicForm
@ -58,13 +67,14 @@ export function DailyLogsPage() {
setRefreshKey(k => k + 1); setRefreshKey(k => k + 1);
}} }}
onCancel={() => setIsCreating(false)} onCancel={() => setIsCreating(false)}
onActivityChange={setCreateTitle}
/> />
</Modal> </Modal>
<Modal <Modal
open={punchOutInstanceId != null} open={punchOutInstanceId != null}
onClose={() => setPunchOutInstanceId(null)} onClose={() => setPunchOutInstanceId(null)}
title="Punch Out" title={punchOutTitle}
width="md" width="md"
> >
{punchOutInstanceId != null && ( {punchOutInstanceId != null && (
@ -77,6 +87,7 @@ export function DailyLogsPage() {
setRefreshKey(k => k + 1); setRefreshKey(k => k + 1);
}} }}
onCancel={() => setPunchOutInstanceId(null)} onCancel={() => setPunchOutInstanceId(null)}
onActivityChange={setPunchOutTitle}
/> />
)} )}
</Modal> </Modal>

View File

@ -6,6 +6,7 @@ import { useState } from 'react';
import { Button } from '../components/buttons/Button'; import { Button } from '../components/buttons/Button';
import { Plus } from 'lucide-react'; import { Plus } from 'lucide-react';
import { DynamicForm } from '../components/forms/DynamicForm'; import { DynamicForm } from '../components/forms/DynamicForm';
import { formatActivityName } from '../lib/format';
import { ORDER_BOOKING } from '../api/config'; import { ORDER_BOOKING } from '../api/config';
import { orderBookingClient } from '../api/clients'; import { orderBookingClient } from '../api/clients';
import { useAuth } from '../auth/context'; import { useAuth } from '../auth/context';
@ -15,6 +16,7 @@ export function MyOrdersPage() {
const instanceId = params.instanceId ? Number(params.instanceId) : undefined; const instanceId = params.instanceId ? Number(params.instanceId) : undefined;
const navigate = useNavigate(); const navigate = useNavigate();
const [isCreating, setIsCreating] = useState(false); const [isCreating, setIsCreating] = useState(false);
const [createTitle, setCreateTitle] = useState(formatActivityName(ORDER_BOOKING.activities.LOG_VISIT.uid));
const [refreshKey, setRefreshKey] = useState(0); const [refreshKey, setRefreshKey] = useState(0);
const { userEmail } = useAuth(); const { userEmail } = useAuth();
@ -30,7 +32,10 @@ export function MyOrdersPage() {
if (id != null) navigate(`/my-orders/${id}`); if (id != null) navigate(`/my-orders/${id}`);
}} }}
headerActions={ headerActions={
<Button size="sm" iconLeft={<Plus size={14} />} onClick={() => setIsCreating(true)}> <Button size="sm" iconLeft={<Plus size={14} />} onClick={() => {
setCreateTitle(formatActivityName(ORDER_BOOKING.activities.LOG_VISIT.uid));
setIsCreating(true);
}}>
Place Order Place Order
</Button> </Button>
} }
@ -39,7 +44,7 @@ export function MyOrdersPage() {
<Modal <Modal
open={isCreating} open={isCreating}
onClose={() => setIsCreating(false)} onClose={() => setIsCreating(false)}
title="Place Order" title={createTitle}
width="md" width="md"
> >
<DynamicForm <DynamicForm
@ -50,6 +55,7 @@ export function MyOrdersPage() {
setRefreshKey(k => k + 1); setRefreshKey(k => k + 1);
}} }}
onCancel={() => setIsCreating(false)} onCancel={() => setIsCreating(false)}
onActivityChange={setCreateTitle}
/> />
</Modal> </Modal>

View File

@ -6,6 +6,7 @@ import { useState } from 'react';
import { Button } from '../components/buttons/Button'; import { Button } from '../components/buttons/Button';
import { Plus } from 'lucide-react'; import { Plus } from 'lucide-react';
import { DynamicForm } from '../components/forms/DynamicForm'; import { DynamicForm } from '../components/forms/DynamicForm';
import { formatActivityName } from '../lib/format';
import { ORDER_BOOKING } from '../api/config'; import { ORDER_BOOKING } from '../api/config';
import { orderBookingClient } from '../api/clients'; import { orderBookingClient } from '../api/clients';
@ -14,6 +15,7 @@ export function OrdersPage() {
const instanceId = params.instanceId ? Number(params.instanceId) : undefined; const instanceId = params.instanceId ? Number(params.instanceId) : undefined;
const navigate = useNavigate(); const navigate = useNavigate();
const [isCreating, setIsCreating] = useState(false); const [isCreating, setIsCreating] = useState(false);
const [createTitle, setCreateTitle] = useState(formatActivityName(ORDER_BOOKING.activities.LOG_VISIT.uid));
const [refreshKey, setRefreshKey] = useState(0); const [refreshKey, setRefreshKey] = useState(0);
return ( return (
<> <>
@ -24,7 +26,10 @@ export function OrdersPage() {
if (id != null) navigate(`/orders/${id}`); if (id != null) navigate(`/orders/${id}`);
}} }}
headerActions={ headerActions={
<Button size="sm" iconLeft={<Plus size={14} />} onClick={() => setIsCreating(true)}> <Button size="sm" iconLeft={<Plus size={14} />} onClick={() => {
setCreateTitle(formatActivityName(ORDER_BOOKING.activities.LOG_VISIT.uid));
setIsCreating(true);
}}>
Place Order Place Order
</Button> </Button>
} }
@ -33,7 +38,7 @@ export function OrdersPage() {
<Modal <Modal
open={isCreating} open={isCreating}
onClose={() => setIsCreating(false)} onClose={() => setIsCreating(false)}
title="Place Order" title={createTitle}
width="md" width="md"
> >
<DynamicForm <DynamicForm
@ -44,6 +49,7 @@ export function OrdersPage() {
setRefreshKey(k => k + 1); setRefreshKey(k => k + 1);
}} }}
onCancel={() => setIsCreating(false)} onCancel={() => setIsCreating(false)}
onActivityChange={setCreateTitle}
/> />
</Modal> </Modal>

View File

@ -6,6 +6,7 @@ import { StoreDetail } from '../components/dv';
import { Button } from '../components/buttons/Button'; import { Button } from '../components/buttons/Button';
import { Plus } from 'lucide-react'; import { Plus } from 'lucide-react';
import { DynamicForm } from '../components/forms/DynamicForm'; import { DynamicForm } from '../components/forms/DynamicForm';
import { formatActivityName } from '../lib/format';
import { STORE } from '../api/config'; import { STORE } from '../api/config';
import { storeClient } from '../api/clients'; import { storeClient } from '../api/clients';
@ -14,7 +15,9 @@ export function StoresPage() {
const instanceId = params.instanceId ? Number(params.instanceId) : undefined; const instanceId = params.instanceId ? Number(params.instanceId) : undefined;
const navigate = useNavigate(); const navigate = useNavigate();
const [isCreating, setIsCreating] = useState(false); const [isCreating, setIsCreating] = useState(false);
const [createTitle, setCreateTitle] = useState(formatActivityName(STORE.activities.INIT.uid));
const [editingInstanceId, setEditingInstanceId] = useState<number | string | null>(null); const [editingInstanceId, setEditingInstanceId] = useState<number | string | null>(null);
const [editTitle, setEditTitle] = useState(formatActivityName(STORE.activities.EDIT_STORE.uid));
const [refreshKey, setRefreshKey] = useState(0); const [refreshKey, setRefreshKey] = useState(0);
return ( return (
@ -26,12 +29,18 @@ export function StoresPage() {
if (id != null) navigate(`/stores/${id}`); if (id != null) navigate(`/stores/${id}`);
}} }}
headerActions={ headerActions={
<Button size="sm" iconLeft={<Plus size={14} />} onClick={() => setIsCreating(true)}> <Button size="sm" iconLeft={<Plus size={14} />} onClick={() => {
setCreateTitle(formatActivityName(STORE.activities.INIT.uid));
setIsCreating(true);
}}>
Create Store Create Store
</Button> </Button>
} }
rowActions={(row) => ( rowActions={(row) => (
<Button size="sm" variant="secondary" onClick={() => setEditingInstanceId(row.instance_id as string | number)}> <Button size="sm" variant="secondary" onClick={() => {
setEditTitle(formatActivityName(STORE.activities.EDIT_STORE.uid));
setEditingInstanceId(row.instance_id as string | number);
}}>
Edit Edit
</Button> </Button>
)} )}
@ -40,7 +49,7 @@ export function StoresPage() {
<Modal <Modal
open={isCreating} open={isCreating}
onClose={() => setIsCreating(false)} onClose={() => setIsCreating(false)}
title="Create Store" title={createTitle}
width="md" width="md"
> >
<DynamicForm <DynamicForm
@ -51,13 +60,14 @@ export function StoresPage() {
setRefreshKey(k => k + 1); setRefreshKey(k => k + 1);
}} }}
onCancel={() => setIsCreating(false)} onCancel={() => setIsCreating(false)}
onActivityChange={setCreateTitle}
/> />
</Modal> </Modal>
<Modal <Modal
open={editingInstanceId != null} open={editingInstanceId != null}
onClose={() => setEditingInstanceId(null)} onClose={() => setEditingInstanceId(null)}
title="Edit Store" title={editTitle}
width="md" width="md"
> >
{editingInstanceId != null && ( {editingInstanceId != null && (
@ -70,6 +80,7 @@ export function StoresPage() {
setRefreshKey(k => k + 1); setRefreshKey(k => k + 1);
}} }}
onCancel={() => setEditingInstanceId(null)} onCancel={() => setEditingInstanceId(null)}
onActivityChange={setEditTitle}
/> />
)} )}
</Modal> </Modal>

View File

@ -120,10 +120,12 @@
html { html {
height: 100%; height: 100%;
} }
body, body,
#root { #root {
min-height: 100%; min-height: 100%;
} }
body { body {
margin: 0; margin: 0;
font-family: var(--font-sans); font-family: var(--font-sans);
@ -134,47 +136,58 @@
} }
@layer components { @layer components {
/* Brand gradients — not expressible as plain utilities. */ /* Brand gradients — not expressible as plain utilities. */
.bg-sunrise { .bg-sunrise {
background-image: var(--gradient-sunrise); background-image: var(--gradient-sunrise);
} }
.bg-sunrise-soft { .bg-sunrise-soft {
background-image: var(--gradient-sunrise-soft); background-image: var(--gradient-sunrise-soft);
} }
.bg-navy-grad { .bg-navy-grad {
background-image: var(--gradient-navy); background-image: var(--gradient-navy);
} }
/* Tabular figures for aligning currency & counts. */ /* Tabular figures for aligning currency & counts. */
.nums { .nums {
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
} }
/* Primary focus ring on inputs/selects. */ /* Primary focus ring on inputs/selects. */
.focus-ring:focus-within { .focus-ring:focus-within {
border-color: var(--z-btn-primary-bg); border-color: var(--z-btn-primary-bg);
box-shadow: var(--shadow-focus); box-shadow: var(--shadow-focus);
} }
/* Slim, theme-tinted scrollbar for in-panel scroll areas. */ /* Slim, theme-tinted scrollbar for in-panel scroll areas. */
.scrollbar-slim { .scrollbar-slim {
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: var(--border-default) transparent; scrollbar-color: var(--border-default) transparent;
} }
.scrollbar-slim::-webkit-scrollbar { .scrollbar-slim::-webkit-scrollbar {
width: 10px; width: 10px;
height: 10px; height: 10px;
} }
.scrollbar-slim::-webkit-scrollbar-track { .scrollbar-slim::-webkit-scrollbar-track {
background: transparent; background: transparent;
} }
.scrollbar-slim::-webkit-scrollbar-thumb { .scrollbar-slim::-webkit-scrollbar-thumb {
background-color: var(--border-default); background-color: var(--border-default);
background-clip: padding-box; background-clip: padding-box;
border: 3px solid transparent; border: 3px solid transparent;
border-radius: 9999px; border-radius: 9999px;
} }
.scrollbar-slim:hover::-webkit-scrollbar-thumb { .scrollbar-slim:hover::-webkit-scrollbar-thumb {
background-color: var(--text-faint); background-color: var(--text-faint);
} }
} }
/* root variable */ /* root variable */
:root { :root {
@ -223,9 +236,9 @@
--tiles-count-size: 20px; --tiles-count-size: 20px;
/* button */ /* button */
--z-btn-primary-bg: #0058be; --z-btn-primary-bg: linear-gradient(91deg, #1b37a5 0.17%, #2e56e1 99.89%);
--z-btn-primary-color: #fff; --z-btn-primary-color: #fff;
--primary-btn-active: #196ed0; --primary-btn-active: linear-gradient(91deg, #3553c5 0.17%, #4a70f3 99.89%);
--primary-btn-activeClr: #fff; --primary-btn-activeClr: #fff;
--z-btn-secondary-bg: #f4f4f4; --z-btn-secondary-bg: #f4f4f4;
--z-btn-secondary-color: #10182b; --z-btn-secondary-color: #10182b;
@ -492,4 +505,4 @@
--z-border-success-200: #6ce9a6; --z-border-success-200: #6ce9a6;
--z-border-success-300: #32d584; --z-border-success-300: #32d584;
--z-border-success-400: #12b76a; --z-border-success-400: #12b76a;
} }