updates on the ui changes and frully removed the mui and converted into astryx and color change
This commit is contained in:
@@ -1,15 +1,39 @@
|
||||
// Astryx brand theme — extends the stock "neutral" theme with Doormile's
|
||||
// brand red so migrated surfaces match the existing DT token palette
|
||||
// brand colour so migrated surfaces match the existing DT token palette
|
||||
// (see themes/dt/tokens.js). Runtime-injected (not `astryx theme build`)
|
||||
// since this repo doesn't do SSR — see `astryx docs theme`.
|
||||
import { defineTheme } from '@astryxdesign/core/theme';
|
||||
import { neutralTheme } from '@astryxdesign/theme-neutral';
|
||||
import { DT } from 'themes/dt/tokens';
|
||||
|
||||
// The brand is pure black. Astryx's `color.accent` generator derives a whole
|
||||
// ramp from the accent's hue + lightness, and black has NO hue and zero
|
||||
// lightness — feeding it `#000000` made the generator clamp it into a mid-tone
|
||||
// and invent a hue, which rendered every primary button magenta (#A23760).
|
||||
//
|
||||
// So the accent tokens are pinned explicitly via `tokens` instead, which
|
||||
// `defineTheme` documents as taking precedence over scale-generated values.
|
||||
// Each entry is a [light, dark] pair. `--color-accent-muted` has to be listed
|
||||
// too: the generated value inlines the accent hex inside a color-mix() rather
|
||||
// than referencing var(--color-accent), so it does not follow automatically.
|
||||
const BRAND_ON_LIGHT = DT.brand; // #000000
|
||||
const BRAND_ON_DARK = '#FFFFFF';
|
||||
|
||||
export const doormileTheme = defineTheme({
|
||||
name: 'doormile',
|
||||
extends: neutralTheme,
|
||||
color: { accent: DT.brand, neutralStyle: 'cool' },
|
||||
color: { neutralStyle: 'cool' },
|
||||
tokens: {
|
||||
'--color-accent': [BRAND_ON_LIGHT, BRAND_ON_DARK],
|
||||
'--color-icon-accent': [BRAND_ON_LIGHT, BRAND_ON_DARK],
|
||||
'--color-text-accent': [BRAND_ON_LIGHT, BRAND_ON_DARK],
|
||||
// Text/icon colour that sits ON a filled accent surface — inverted.
|
||||
'--color-on-accent': ['#FFFFFF', '#000000'],
|
||||
'--color-accent-muted': [
|
||||
`color-mix(in srgb, ${BRAND_ON_LIGHT} 12%, transparent)`,
|
||||
`color-mix(in srgb, ${BRAND_ON_DARK} 20%, transparent)`
|
||||
]
|
||||
},
|
||||
components: {
|
||||
card: { base: { borderRadius: `${DT.radiusCard}px` } },
|
||||
'text-input': { base: { borderRadius: `${DT.radiusInner}px` } }
|
||||
|
||||
83
src/themes/dt/primitives.js
Normal file
83
src/themes/dt/primitives.js
Normal file
@@ -0,0 +1,83 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Center } from '@astryxdesign/core/Center';
|
||||
|
||||
import { DT, soft } from './tokens';
|
||||
|
||||
// ============================================================================
|
||||
// Shared DT primitives — the tiny components that every DT-styled operator
|
||||
// page used to redeclare verbatim at the top of its own file.
|
||||
//
|
||||
// They were byte-identical in all 6 copies, so the duplication bought nothing
|
||||
// and made the pages drift apart whenever one was tweaked. `deliveries.js` is
|
||||
// the visual reference for both (see root CLAUDE.md §6).
|
||||
// ============================================================================
|
||||
|
||||
// Soft popup surface. Under MUI this was a `PaperComponent` handed to every
|
||||
// Autocomplete; Astryx's Selector/Typeahead own their own popup chrome, so
|
||||
// this now only serves the few hand-rolled dropdowns that remain. Kept as a
|
||||
// style object rather than a component for exactly that reason.
|
||||
export const softPopupStyle = {
|
||||
marginTop: 6,
|
||||
background: DT.surface,
|
||||
borderRadius: DT.radiusInner + 'px',
|
||||
boxShadow: DT.shadowPop,
|
||||
border: `1px solid ${DT.borderSubtle}`,
|
||||
overflow: 'hidden'
|
||||
};
|
||||
|
||||
// Scroll container for a table. Astryx's Table renders a bare <table> with no
|
||||
// sticky-header or max-height affordance (MUI's TableContainer used to provide that),
|
||||
// so pages wrap it in this. The brand-red scrollbar can't be expressed inline
|
||||
// — ::-webkit-scrollbar-* are pseudo-elements — hence the one-time <style>.
|
||||
export const TableScroll = ({ maxHeight = 'calc(100vh - 260px)', minWidth, children }) => (
|
||||
<>
|
||||
<style>{`
|
||||
.dt-table-scroll { overflow: auto; }
|
||||
.dt-table-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
|
||||
.dt-table-scroll::-webkit-scrollbar-track { background-color: ${DT.surfaceAlt}; }
|
||||
.dt-table-scroll::-webkit-scrollbar-thumb {
|
||||
background-color: ${DT.brand}55; border-radius: 8px;
|
||||
}
|
||||
.dt-table-scroll::-webkit-scrollbar-thumb:hover { background-color: ${DT.brand}; }
|
||||
.dt-table-scroll thead th { position: sticky; top: 0; z-index: 2; background-color: ${DT.surfaceAlt}; }
|
||||
`}</style>
|
||||
<div className="dt-table-scroll" style={{ maxHeight }}>
|
||||
<div style={{ minWidth }}>{children}</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
TableScroll.propTypes = {
|
||||
maxHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
minWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
// Colored icon chip — flips between filled and soft based on `selected`.
|
||||
// Astryx's own `Avatar` is for people (src / initials / status corner), so a
|
||||
// tinted `Center` is the right primitive for an icon swatch. The accent is a
|
||||
// caller-supplied hex, hence the inline style.
|
||||
export const AccentAvatar = ({ color, selected, size = 24, children }) => (
|
||||
<Center
|
||||
isInline
|
||||
width={size}
|
||||
height={size}
|
||||
style={{
|
||||
flexShrink: 0,
|
||||
borderRadius: '50%',
|
||||
backgroundColor: selected ? color : soft(color),
|
||||
color: selected ? '#fff' : color,
|
||||
transition: 'background-color 0.15s, color 0.15s'
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Center>
|
||||
);
|
||||
|
||||
AccentAvatar.propTypes = {
|
||||
color: PropTypes.string,
|
||||
selected: PropTypes.bool,
|
||||
size: PropTypes.number,
|
||||
children: PropTypes.node
|
||||
};
|
||||
@@ -23,7 +23,31 @@ export const DT = {
|
||||
divider: '#f1f5f9',
|
||||
surface: '#ffffff',
|
||||
surfaceAlt: '#f8fafc',
|
||||
brand: '#C01227'
|
||||
brand: '#000000'
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Semantic status palette — lifecycle colours, deliberately distinct from the
|
||||
// brand (see root CLAUDE.md §6). Pages have historically inlined these hexes;
|
||||
// new code should reference STATUS so there is one place to change them.
|
||||
// This also replaces the `theme.palette.error/success/...` lookups that used
|
||||
// to pull the same colours out of the MUI theme.
|
||||
// ---------------------------------------------------------------------------
|
||||
export const STATUS = {
|
||||
pending: '#f59e0b', // amber
|
||||
accepted: '#6366f1', // indigo
|
||||
arrived: '#06b6d4', // cyan
|
||||
picked: '#8b5cf6', // light purple
|
||||
active: '#14b8a6', // teal
|
||||
skipped: '#f97316', // orange
|
||||
delivered: '#10b981', // emerald
|
||||
cancelled: '#ef4444', // red
|
||||
info: '#0ea5e9', // sky
|
||||
muted: '#94a3b8', // slate
|
||||
// Aliases for non-lifecycle usage (network banners, validation, …).
|
||||
success: '#10b981',
|
||||
warning: '#f59e0b',
|
||||
error: '#ef4444'
|
||||
};
|
||||
|
||||
// Quick alpha helpers (hex + percentage suffix).
|
||||
@@ -54,3 +78,53 @@ export const pillFieldSx = () => ({
|
||||
},
|
||||
'& .MuiAutocomplete-endAdornment .MuiSvgIcon-root': { color: DT.textMuted }
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Table chrome — lifted verbatim from deliveries.js, the design reference for
|
||||
// every operator list page (root CLAUDE.md §6). These three used to be
|
||||
// copy-pasted into each page's <TableContainer>/<TableHead>/<TableRow>, which
|
||||
// is how pages drifted apart (grey scrollbars on some, brand-red on others).
|
||||
// Spread them instead of restating the rules:
|
||||
//
|
||||
// <TableContainer sx={{ maxHeight: ..., ...tableScrollSx }}>
|
||||
// <Table stickyHeader>
|
||||
// <TableHead><TableRow sx={tableHeadSx}>...
|
||||
// <TableBody><TableRow sx={tableRowSx}>...
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Brand-red scrollbar. Track is the page's alt surface so the gutter reads as
|
||||
// part of the table rather than a hole in it.
|
||||
export const tableScrollSx = {
|
||||
overflow: 'auto',
|
||||
'&::-webkit-scrollbar': { width: '10px', height: '10px', cursor: 'pointer' },
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
backgroundColor: edge(DT.brand),
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
'&:hover': { backgroundColor: DT.brand }
|
||||
},
|
||||
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
|
||||
};
|
||||
|
||||
// Uppercase muted header row on the alt surface.
|
||||
export const tableHeadSx = {
|
||||
'& th': {
|
||||
backgroundColor: DT.surfaceAlt,
|
||||
color: DT.textSecondary,
|
||||
fontSize: { xs: 10, md: 11 },
|
||||
fontWeight: 800,
|
||||
letterSpacing: 0.6,
|
||||
textTransform: 'uppercase',
|
||||
whiteSpace: 'nowrap',
|
||||
borderBottom: `1px solid ${DT.borderSubtle}`,
|
||||
py: { xs: 1, md: 1.25 },
|
||||
px: { xs: 1, md: 2 }
|
||||
}
|
||||
};
|
||||
|
||||
// Body row: hairline divider, tinted hover. No shadow on hover — see the
|
||||
// design-system "don'ts" in root CLAUDE.md §6.
|
||||
export const tableRowSx = {
|
||||
'& td': { borderBottom: `1px solid ${DT.divider}` },
|
||||
'&:hover': { backgroundColor: DT.surfaceAlt }
|
||||
};
|
||||
|
||||
@@ -117,11 +117,11 @@ export default function ThemeCustomization({ children }) {
|
||||
textRendering: 'optimizeLegibility'
|
||||
},
|
||||
// Thin, unobtrusive scrollbars (Stripe/Linear style) instead of the
|
||||
// chunky 14px solid-purple bar. Track is transparent; the thumb is a
|
||||
// soft slate that tints toward brand purple on hover.
|
||||
// chunky 14px solid bar. Track is transparent; the thumb is a soft
|
||||
// translucent black that deepens toward the brand black on hover.
|
||||
'*': {
|
||||
scrollbarWidth: 'thin', // Firefox
|
||||
scrollbarColor: 'rgba(192, 18, 39, 0.28) transparent'
|
||||
scrollbarColor: 'rgba(0, 0, 0, 0.28) transparent'
|
||||
},
|
||||
'*::-webkit-scrollbar': {
|
||||
width: '10px',
|
||||
@@ -131,13 +131,13 @@ export default function ThemeCustomization({ children }) {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
'*::-webkit-scrollbar-thumb': {
|
||||
backgroundColor: 'rgba(192, 18, 39, 0.26)',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.26)',
|
||||
borderRadius: '8px',
|
||||
border: '2px solid transparent',
|
||||
backgroundClip: 'padding-box'
|
||||
},
|
||||
'*::-webkit-scrollbar-thumb:hover': {
|
||||
backgroundColor: 'rgba(192, 18, 39, 0.45)'
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.45)'
|
||||
},
|
||||
'*::-webkit-scrollbar-corner': {
|
||||
backgroundColor: 'transparent'
|
||||
|
||||
@@ -23,10 +23,10 @@ export default function Autocomplete() {
|
||||
borderRadius: 8,
|
||||
margin: '1px 0',
|
||||
'&[aria-selected="true"]': {
|
||||
backgroundColor: 'rgba(192, 18, 39, 0.08)'
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.08)'
|
||||
},
|
||||
'&.Mui-focused': {
|
||||
backgroundColor: 'rgba(192, 18, 39, 0.06)'
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.06)'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -40,16 +40,16 @@ const Default = (colors) => {
|
||||
// contrastText
|
||||
// },
|
||||
primary: {
|
||||
lighter: '#F5DBDE',
|
||||
100: '#E9ADB4',
|
||||
200: '#DD7E8A',
|
||||
light: '#D25463',
|
||||
400: '#D25463',
|
||||
main: '#C01227',
|
||||
dark: '#910E1D',
|
||||
700: '#6D0A16',
|
||||
darker: '#48070F',
|
||||
900: '#2B0409',
|
||||
lighter: '#F2F2F2',
|
||||
100: '#D9D9D9',
|
||||
200: '#BFBFBF',
|
||||
light: '#3A3A3A',
|
||||
400: '#3A3A3A',
|
||||
main: '#000000',
|
||||
dark: '#262626',
|
||||
700: '#1A1A1A',
|
||||
darker: '#000000',
|
||||
900: '#000000',
|
||||
contrastText: '#FFFFFF'
|
||||
},
|
||||
secondary: {
|
||||
|
||||
Reference in New Issue
Block a user