mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-22 00:24:23 +01:00
ui-v2: match tile / chart designs (#2633)
This commit is contained in:
BIN
ui-v2/src/assets/fonts/CashSansMono-Light.woff2
Normal file
BIN
ui-v2/src/assets/fonts/CashSansMono-Light.woff2
Normal file
Binary file not shown.
BIN
ui-v2/src/assets/fonts/CashSansMono-Regular.woff2
Normal file
BIN
ui-v2/src/assets/fonts/CashSansMono-Regular.woff2
Normal file
Binary file not shown.
@@ -1,7 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTimelineStyles } from '../../hooks/useTimelineStyles.ts';
|
import { useTimelineStyles } from '../../hooks/useTimelineStyles.ts';
|
||||||
import { ChartConfig, ChartContainer } from "@/components/ui/chart.tsx";
|
import {
|
||||||
import { BarChart, Bar, LineChart, Line, ResponsiveContainer, Tooltip } from 'recharts';
|
ChartConfig,
|
||||||
|
ChartContainer,
|
||||||
|
ChartTooltip,
|
||||||
|
ChartTooltipContent,
|
||||||
|
} from "@/components/ui/chart";
|
||||||
|
import { BarChart, Bar, LineChart, Line, CartesianGrid, XAxis, ResponsiveContainer } from 'recharts';
|
||||||
|
|
||||||
interface ChartTileProps {
|
interface ChartTileProps {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -27,17 +32,14 @@ export default function ChartTile({
|
|||||||
// Convert the data array to the format expected by recharts
|
// Convert the data array to the format expected by recharts
|
||||||
const chartData = data.map((value, index) => ({
|
const chartData = data.map((value, index) => ({
|
||||||
value,
|
value,
|
||||||
index: `Point ${index + 1}`
|
point: `P${index + 1}`
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Chart configuration
|
// Chart configuration with proper color variables
|
||||||
const chartConfig = {
|
const chartConfig = {
|
||||||
value: {
|
value: {
|
||||||
label: title,
|
label: title,
|
||||||
theme: {
|
color: variant === 'line' ? 'var(--chart-2)' : 'var(--chart-1)'
|
||||||
light: variant === 'line' ? '#0B54DE' : '#4CAF50',
|
|
||||||
dark: variant === 'line' ? '#00CAF7' : '#4CAF50'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} satisfies ChartConfig;
|
} satisfies ChartConfig;
|
||||||
|
|
||||||
@@ -45,54 +47,94 @@ export default function ChartTile({
|
|||||||
<div
|
<div
|
||||||
className={`
|
className={`
|
||||||
flex flex-col justify-between
|
flex flex-col justify-between
|
||||||
w-[320px] h-[380px]
|
w-[320px] min-h-[380px]
|
||||||
${contentCardStyle}
|
${contentCardStyle}
|
||||||
rounded-[18px]
|
rounded-[18px]
|
||||||
relative
|
relative
|
||||||
overflow-hidden
|
overflow-hidden
|
||||||
transition-all duration-200
|
transition-all duration-200
|
||||||
hover:scale-[1.02]
|
hover:scale-[1.02]
|
||||||
|
bg-background-default text-text-default
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{/* Header section with icon */}
|
{/* Header section with icon */}
|
||||||
<div className="p-4 space-y-4">
|
<div className="p-4 space-y-4">
|
||||||
<div className="w-6 h-6">
|
<div className="w-6 h-6 text-text-default">
|
||||||
{icon}
|
{icon}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className="text-gray-600 dark:text-white/40 text-sm mb-1">{title}</div>
|
<div className="text-text-muted text-sm mb-1">{title}</div>
|
||||||
<div className="text-gray-900 dark:text-white text-2xl font-semibold">
|
<div className="text-text-default text-2xl font-semibold">
|
||||||
{value}
|
{value}
|
||||||
{trend && <span className="ml-1 text-sm">{trend}</span>}
|
{trend && <span className="ml-1 text-sm text-text-muted">{trend}</span>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Chart Container */}
|
{/* Chart Container */}
|
||||||
<div className="w-full h-[160px] px-4">
|
<div className="w-full h-[200px] px-4 pb-6">
|
||||||
<ChartContainer config={chartConfig}>
|
<ChartContainer
|
||||||
|
config={chartConfig}
|
||||||
|
className="[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-tooltip-wrapper]:!pointer-events-none"
|
||||||
|
>
|
||||||
|
<ResponsiveContainer width="100%" height="100%">
|
||||||
{variant === 'line' ? (
|
{variant === 'line' ? (
|
||||||
<LineChart data={chartData}>
|
<LineChart data={chartData} margin={{ top: 10, right: 10, bottom: 0, left: -20 }}>
|
||||||
|
<CartesianGrid vertical={false} className="stroke-border/50" />
|
||||||
|
<XAxis
|
||||||
|
dataKey="point"
|
||||||
|
tickLine={false}
|
||||||
|
tickMargin={10}
|
||||||
|
axisLine={false}
|
||||||
|
height={40}
|
||||||
|
tick={{ fill: 'var(--text-muted)' }}
|
||||||
|
/>
|
||||||
|
<ChartTooltip
|
||||||
|
content={
|
||||||
|
<ChartTooltipContent
|
||||||
|
className="border-border/50 bg-background-default text-text-default min-w-[180px] [&_.flex.flex-1]:gap-4 [&_.flex.flex-1>span]:whitespace-nowrap"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Line
|
<Line
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey="value"
|
dataKey="value"
|
||||||
stroke="var(--color-value)"
|
stroke="var(--chart-2)"
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
dot={{ fill: 'var(--color-value)', r: 4 }}
|
dot={{ fill: 'var(--chart-2)', r: 4 }}
|
||||||
/>
|
/>
|
||||||
<Tooltip />
|
|
||||||
</LineChart>
|
</LineChart>
|
||||||
) : (
|
) : (
|
||||||
<BarChart data={chartData}>
|
<BarChart data={chartData} margin={{ top: 10, right: 10, bottom: 0, left: 10 }}>
|
||||||
|
<CartesianGrid vertical={false} className="stroke-border/50" />
|
||||||
|
<XAxis
|
||||||
|
dataKey="point"
|
||||||
|
tickLine={false}
|
||||||
|
tickMargin={10}
|
||||||
|
axisLine={false}
|
||||||
|
height={40}
|
||||||
|
tick={{ fill: 'var(--text-muted)' }}
|
||||||
|
interval={0}
|
||||||
|
/>
|
||||||
|
<ChartTooltip
|
||||||
|
cursor={false}
|
||||||
|
content={
|
||||||
|
<ChartTooltipContent
|
||||||
|
indicator="dashed"
|
||||||
|
className="border-border/50 bg-background-default text-text-default min-w-[180px] [&_.flex.flex-1]:gap-4 [&_.flex.flex-1>span]:whitespace-nowrap"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Bar
|
<Bar
|
||||||
dataKey="value"
|
dataKey="value"
|
||||||
fill="var(--color-value)"
|
fill="var(--chart-1)"
|
||||||
radius={[4, 4, 0, 0]}
|
radius={4}
|
||||||
|
maxBarSize={32}
|
||||||
/>
|
/>
|
||||||
<Tooltip />
|
|
||||||
</BarChart>
|
</BarChart>
|
||||||
)}
|
)}
|
||||||
|
</ResponsiveContainer>
|
||||||
</ChartContainer>
|
</ChartContainer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useTimelineStyles } from '../../hooks/useTimelineStyles';
|
import { useTimelineStyles } from '../../hooks/useTimelineStyles';
|
||||||
import { ChartConfig, ChartContainer } from "@/components/ui/chart";
|
import { ChartConfig, ChartContainer } from "@/components/ui/chart";
|
||||||
import { PieChart, Pie, Cell, Tooltip, Legend } from 'recharts';
|
import { PieChart, Pie, Cell, Sector, ResponsiveContainer } from 'recharts';
|
||||||
|
|
||||||
interface PieChartSegment {
|
interface PieChartSegment {
|
||||||
value: number;
|
value: number;
|
||||||
@@ -16,6 +16,90 @@ interface PieChartTileProps {
|
|||||||
date?: Date;
|
date?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom label renderer with connecting lines
|
||||||
|
const renderCustomizedLabel = ({
|
||||||
|
cx,
|
||||||
|
cy,
|
||||||
|
midAngle,
|
||||||
|
innerRadius,
|
||||||
|
outerRadius,
|
||||||
|
percent,
|
||||||
|
payload,
|
||||||
|
fill,
|
||||||
|
}: any) => {
|
||||||
|
const RADIAN = Math.PI / 180;
|
||||||
|
const sin = Math.sin(-RADIAN * midAngle);
|
||||||
|
const cos = Math.cos(-RADIAN * midAngle);
|
||||||
|
|
||||||
|
// Adjust these values to position labels closer to the pie
|
||||||
|
const labelOffset = 12;
|
||||||
|
const labelDistance = 18;
|
||||||
|
|
||||||
|
// Calculate positions with shorter distances
|
||||||
|
const mx = cx + (outerRadius + labelOffset) * cos;
|
||||||
|
const my = cy + (outerRadius + labelOffset) * sin;
|
||||||
|
const ex = mx + (cos >= 0 ? 1 : -1) * labelDistance;
|
||||||
|
const ey = my;
|
||||||
|
|
||||||
|
// Text anchor based on which side of the pie we're on
|
||||||
|
const textAnchor = cos >= 0 ? "start" : "end";
|
||||||
|
|
||||||
|
// Calculate percentage
|
||||||
|
const value = (percent * 100).toFixed(0);
|
||||||
|
|
||||||
|
// Determine if label should be on top or bottom half for potential y-offset
|
||||||
|
const isTopHalf = my < cy;
|
||||||
|
const yOffset = isTopHalf ? -2 : 2;
|
||||||
|
|
||||||
|
// Force specific adjustments for "In Progress" label if needed
|
||||||
|
const isInProgress = payload.name === "In Progress";
|
||||||
|
const adjustedEx = isInProgress ? ex - 5 : ex;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<g>
|
||||||
|
{/* Label line - using absolute coordinates for reliability */}
|
||||||
|
<path
|
||||||
|
d={`M${cx + outerRadius * cos},${cy + outerRadius * sin}L${mx},${my}L${adjustedEx},${ey}`}
|
||||||
|
stroke={fill}
|
||||||
|
strokeWidth={1}
|
||||||
|
fill="none"
|
||||||
|
style={{ opacity: 1 }}
|
||||||
|
/>
|
||||||
|
{/* Label text with adjusted position */}
|
||||||
|
<text
|
||||||
|
x={adjustedEx + (cos >= 0 ? 5 : -5)}
|
||||||
|
y={ey + yOffset}
|
||||||
|
textAnchor={textAnchor}
|
||||||
|
fill="var(--text-default)"
|
||||||
|
className="text-[10px]"
|
||||||
|
style={{
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{payload.name} ({value}%)
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Active shape renderer for hover effect
|
||||||
|
const renderActiveShape = (props: any) => {
|
||||||
|
const { cx, cy, innerRadius, outerRadius, startAngle, endAngle, fill } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sector
|
||||||
|
cx={cx}
|
||||||
|
cy={cy}
|
||||||
|
innerRadius={innerRadius}
|
||||||
|
outerRadius={outerRadius + 4}
|
||||||
|
startAngle={startAngle}
|
||||||
|
endAngle={endAngle}
|
||||||
|
fill={fill}
|
||||||
|
cornerRadius={4}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default function PieChartTile({
|
export default function PieChartTile({
|
||||||
title,
|
title,
|
||||||
icon,
|
icon,
|
||||||
@@ -23,102 +107,96 @@ export default function PieChartTile({
|
|||||||
date
|
date
|
||||||
}: PieChartTileProps) {
|
}: PieChartTileProps) {
|
||||||
const { contentCardStyle } = useTimelineStyles(date);
|
const { contentCardStyle } = useTimelineStyles(date);
|
||||||
|
const [activeIndex, setActiveIndex] = useState<number>(0);
|
||||||
|
|
||||||
// Convert segments to the format expected by recharts
|
// Convert segments to the format expected by recharts and assign chart colors
|
||||||
const chartData = segments.map(segment => ({
|
const chartData = segments.map((segment, index) => ({
|
||||||
name: segment.label,
|
name: segment.label,
|
||||||
value: segment.value
|
value: segment.value,
|
||||||
|
chartColor: `var(--chart-${index + 1})` // Use chart-1, chart-2, chart-3, etc.
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Create chart configuration with theme colors
|
// Create chart configuration using the chart color variables
|
||||||
const chartConfig = segments.reduce((config, segment) => {
|
const chartConfig = {
|
||||||
config[segment.label] = {
|
[segments[0].label.toLowerCase()]: {
|
||||||
label: segment.label,
|
label: segments[0].label,
|
||||||
color: segment.color
|
color: 'var(--chart-1)'
|
||||||
};
|
},
|
||||||
return config;
|
[segments[1].label.toLowerCase()]: {
|
||||||
}, {} as ChartConfig);
|
label: segments[1].label,
|
||||||
|
color: 'var(--chart-2)'
|
||||||
|
},
|
||||||
|
[segments[2].label.toLowerCase()]: {
|
||||||
|
label: segments[2].label,
|
||||||
|
color: 'var(--chart-3)'
|
||||||
|
}
|
||||||
|
} satisfies ChartConfig;
|
||||||
|
|
||||||
// Custom tooltip formatter
|
const onPieEnter = (_: any, index: number) => {
|
||||||
const tooltipFormatter = (value: number, name: string) => {
|
setActiveIndex(index);
|
||||||
const total = segments.reduce((sum, segment) => sum + segment.value, 0);
|
|
||||||
const percentage = ((value / total) * 100).toFixed(1);
|
|
||||||
return [`${percentage}%`, name];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`
|
className={`
|
||||||
flex flex-col
|
flex flex-col
|
||||||
w-[320px] h-[380px]
|
w-[320px] min-h-[380px]
|
||||||
${contentCardStyle}
|
${contentCardStyle}
|
||||||
rounded-[18px]
|
rounded-[18px]
|
||||||
relative
|
relative
|
||||||
overflow-hidden
|
overflow-hidden
|
||||||
transition-all duration-200
|
transition-all duration-200
|
||||||
hover:scale-[1.02]
|
hover:scale-[1.02]
|
||||||
|
bg-background-default text-text-default
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<div className="w-6 h-6 mb-4">
|
<div className="w-6 h-6 mb-4 text-text-default">
|
||||||
{icon}
|
{icon}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-600 dark:text-white/40 text-sm">
|
<div className="text-text-muted text-sm">
|
||||||
{title}
|
{title}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Pie Chart */}
|
{/* Pie Chart */}
|
||||||
<div className="flex-1 flex flex-col items-center">
|
<div className="flex-1 flex items-center justify-center p-4">
|
||||||
<div className="w-full h-[200px]">
|
<div style={{ width: '100%', height: '260px', position: 'relative' }}>
|
||||||
<ChartContainer config={chartConfig}>
|
<ChartContainer config={chartConfig}>
|
||||||
<PieChart>
|
<ResponsiveContainer>
|
||||||
|
<PieChart margin={{ top: 30, right: 40, bottom: 10, left: 40 }}>
|
||||||
<Pie
|
<Pie
|
||||||
|
activeIndex={activeIndex}
|
||||||
|
activeShape={renderActiveShape}
|
||||||
data={chartData}
|
data={chartData}
|
||||||
dataKey="value"
|
|
||||||
nameKey="name"
|
|
||||||
cx="50%"
|
cx="50%"
|
||||||
cy="50%"
|
cy="50%"
|
||||||
innerRadius={0}
|
innerRadius={45}
|
||||||
outerRadius={70}
|
outerRadius={65}
|
||||||
paddingAngle={2}
|
paddingAngle={5}
|
||||||
|
dataKey="value"
|
||||||
|
onMouseEnter={onPieEnter}
|
||||||
|
cornerRadius={4}
|
||||||
|
label={renderCustomizedLabel}
|
||||||
|
labelLine={false}
|
||||||
|
startAngle={90}
|
||||||
|
endAngle={-270}
|
||||||
|
isAnimationActive={false}
|
||||||
>
|
>
|
||||||
{segments.map((segment, index) => (
|
{chartData.map((entry, index) => (
|
||||||
<Cell
|
<Cell
|
||||||
key={`cell-${index}`}
|
key={`cell-${index}`}
|
||||||
fill={segment.color}
|
fill={entry.chartColor}
|
||||||
className="transition-all duration-200 hover:opacity-90"
|
stroke="var(--background-default)"
|
||||||
|
strokeWidth={2}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Pie>
|
</Pie>
|
||||||
<Tooltip formatter={tooltipFormatter} />
|
|
||||||
</PieChart>
|
</PieChart>
|
||||||
|
</ResponsiveContainer>
|
||||||
</ChartContainer>
|
</ChartContainer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Legend */}
|
|
||||||
<div className="mt-2 px-4 w-full space-y-2">
|
|
||||||
{segments.map((segment, index) => {
|
|
||||||
const percentage = ((segment.value / segments.reduce((sum, s) => sum + s.value, 0)) * 100).toFixed(1);
|
|
||||||
return (
|
|
||||||
<div key={index} className="flex items-center justify-between">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<div
|
|
||||||
className="w-3 h-3 rounded-full mr-2"
|
|
||||||
style={{ backgroundColor: segment.color }}
|
|
||||||
/>
|
|
||||||
<span className="text-sm text-gray-600 dark:text-white/60">
|
|
||||||
{segment.label}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span className="text-sm font-medium text-gray-900 dark:text-white">
|
|
||||||
{percentage}%
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,167 +3,257 @@
|
|||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
@layer base {
|
@theme {
|
||||||
:root {
|
/* reset */
|
||||||
|
--color-*: initial;
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
--color-white: #ffffff;
|
||||||
|
--color-black: #000000;
|
||||||
|
|
||||||
|
/* slate */
|
||||||
|
--color-slate-100: #f0f2f8;
|
||||||
|
--color-slate-200: #c8cdd6;
|
||||||
|
--color-slate-300: #a1a7b0;
|
||||||
|
--color-slate-400: #6e747e;
|
||||||
|
--color-slate-500: #4a4e54;
|
||||||
|
--color-slate-600: #2e2e2e;
|
||||||
|
|
||||||
|
/* utility */
|
||||||
|
--color-red-100: #ff6b6b;
|
||||||
|
--color-red-200: #f94b4b;
|
||||||
|
|
||||||
|
--color-blue-100: #7cacff;
|
||||||
|
--color-blue-200: #5c98f9;
|
||||||
|
|
||||||
|
--color-green-100: #a3d795;
|
||||||
|
--color-green-200: #91cb80;
|
||||||
|
|
||||||
|
--color-yellow-100: #ffd966;
|
||||||
|
--color-yellow-200: #fbcd44;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
--spring-easing: linear(
|
|
||||||
0,
|
|
||||||
0.009,
|
|
||||||
0.035 2.1%,
|
|
||||||
0.141,
|
|
||||||
0.281 6.7%,
|
|
||||||
0.723 12.9%,
|
|
||||||
0.938 16.7%,
|
|
||||||
1.017,
|
|
||||||
1.077,
|
|
||||||
1.121,
|
|
||||||
1.149 24.3%,
|
|
||||||
1.159,
|
|
||||||
1.163,
|
|
||||||
1.161,
|
|
||||||
1.154 29.9%,
|
|
||||||
1.129 32.8%,
|
|
||||||
1.051 39.6%,
|
|
||||||
1.017 43.1%,
|
|
||||||
0.991,
|
|
||||||
0.977 51%,
|
|
||||||
0.974 53.8%,
|
|
||||||
0.975 57.1%,
|
|
||||||
0.997 69.8%,
|
|
||||||
1.003 76.9%,
|
|
||||||
1.004 83.8%,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
--spring-duration: 1.333s;
|
|
||||||
|
|
||||||
/* custom slate */
|
/* shape */
|
||||||
--slate: #393838;
|
--radius: 0.5rem;
|
||||||
|
|
||||||
/* block */
|
/* theming accents */
|
||||||
--block-teal: #13bbaf;
|
--background-accent: var(--color-black);
|
||||||
--block-orange: #ff4f00;
|
--border-accent: var(--color-black);
|
||||||
|
--text-accent: var(--color-black);
|
||||||
|
|
||||||
/* start arcade colors */
|
/* Semantic */
|
||||||
--constant-white: #ffffff;
|
--background-default: var(--color-white);
|
||||||
--constant-black: #000000;
|
--background-medium: var(--color-slate-200);
|
||||||
--grey-10: #101010;
|
--background-muted: var(--color-slate-100);
|
||||||
--grey-20: #1e1e1e;
|
--background-inverse: var(--color-black);
|
||||||
--grey-50: #666666;
|
--background-danger: var(--color-red-200);
|
||||||
--grey-60: #959595;
|
--background-success: var(--color-green-200);
|
||||||
--grey-80: #cccccc;
|
--background-info: var(--color-blue-200);
|
||||||
--grey-85: #dadada;
|
--background-warning: var(--color-yellow-200);
|
||||||
--grey-90: #e8e8e8;
|
|
||||||
--grey-95: #f0f0f0;
|
|
||||||
--dark-grey-15: #1a1a1a;
|
|
||||||
--dark-grey-25: #232323;
|
|
||||||
--dark-grey-30: #2a2a2a;
|
|
||||||
--dark-grey-40: #333333;
|
|
||||||
--dark-grey-45: #595959;
|
|
||||||
--dark-grey-60: #878787;
|
|
||||||
--dark-grey-90: #e1e1e1;
|
|
||||||
|
|
||||||
--background-app: var(--constant-white);
|
--border-default: var(--color-slate-200);
|
||||||
--background-prominent: var(--grey-80);
|
--border-input: var(--color-slate-200);
|
||||||
--background-standard: var(--grey-90);
|
--border-strong: var(--color-slate-300);
|
||||||
--background-subtle: var(--grey-95);
|
--border-inverse: var(--color-black);
|
||||||
--background-app-inverse: var(--constant-black);
|
--border-danger: var(--color-red-200);
|
||||||
--background-subtle-inverse: var(--dark-grey-15);
|
--border-success: var(--color-green-200);
|
||||||
--background-standard-inverse: var(--dark-grey-25);
|
--border-warning: var(--color-yellow-200);
|
||||||
--background-prominent-inverse: var(--dark-grey-40);
|
--border-info: var(--color-blue-200);
|
||||||
|
|
||||||
--border-divider: var(--grey-90);
|
--text-default: var(--color-slate-600);
|
||||||
--border-inverse: var(--constant-white);
|
--text-muted: var(--color-slate-400);
|
||||||
--border-prominent: var(--grey-10);
|
--text-inverse: var(--color-white);
|
||||||
--border-standard: var(--grey-60);
|
--text-danger: var(--color-red-200);
|
||||||
--border-subtle: var(--grey-90);
|
--text-success: var(--color-green-200);
|
||||||
|
--text-warning: var(--color-yellow-200);
|
||||||
|
--text-info: var(--color-blue-200);
|
||||||
|
|
||||||
--icon-disabled: var(--grey-60);
|
--ring: var(--border-strong);
|
||||||
--icon-extra-subtle: var(--grey-60);
|
|
||||||
--icon-inverse: var(--constant-white);
|
|
||||||
--icon-prominent: var(--grey-10);
|
|
||||||
--icon-standard: var(--grey-20);
|
|
||||||
--icon-subtle: var(--grey-50);
|
|
||||||
|
|
||||||
--text-placeholder: var(--grey-60);
|
--chart-1: #f6b44a;
|
||||||
--text-prominent: var(--grey-10);
|
--chart-2: #7585ff;
|
||||||
--text-standard: var(--grey-20);
|
--chart-3: #d76a6a;
|
||||||
--text-standard-inverse: var(--dark-grey-90);
|
--chart-4: #d185e0;
|
||||||
--text-subtle: var(--grey-50);
|
--chart-5: #91cb80;
|
||||||
--text-subtle-inverse: var(--dark-grey-60);
|
|
||||||
--text-prominent-inverse: var(--constant-white);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
--sidebar: var(--background-default);
|
||||||
:root {
|
--sidebar-foreground: var(--text-default);
|
||||||
--background-app: var(--constant-black);
|
--sidebar-primary: var(--background-accent);
|
||||||
--background-prominent: var(--dark-grey-40);
|
--sidebar-primary-foreground: var(--text-inverse);
|
||||||
--background-standard: var(--dark-grey-25);
|
--sidebar-accent: var(--background-muted);
|
||||||
--background-subtle: var(--dark-grey-15);
|
--sidebar-accent-foreground: var(--text-default);
|
||||||
--background-app-inverse: var(--constant-white);
|
--sidebar-border: var(--border-default);
|
||||||
--background-subtle-inverse: var(--grey-95);
|
--sidebar-ring: var(--border-default);
|
||||||
--background-standard-inverse: var(--grey-90);
|
}
|
||||||
--background-prominent-inverse: var(--grey-80);
|
|
||||||
|
|
||||||
--border-divider: var(--dark-grey-25);
|
.dark {
|
||||||
--border-inverse: var(--constant-black);
|
/* theming accents */
|
||||||
--border-prominent: var(--constant-white);
|
--background-accent: var(--color-white);
|
||||||
--border-standard: var(--dark-grey-45);
|
--border-accent: var(--color-white);
|
||||||
--border-subtle: var(--dark-grey-25);
|
--text-accent: var(--color-white);
|
||||||
|
|
||||||
--icon-disabled: var(--dark-grey-45);
|
/* semantic */
|
||||||
--icon-extra-subtle: var(--dark-grey-45);
|
--background-default: var(--color-black);
|
||||||
--icon-inverse: var(--constant-black);
|
--background-medium: var(--color-slate-500);
|
||||||
--icon-prominent: var(--constant-white);
|
--background-muted: var(--color-slate-600);
|
||||||
--icon-standard: var(--dark-grey-90);
|
--background-inverse: var(--color-white);
|
||||||
--icon-subtle: var(--dark-grey-60);
|
--background-danger: var(--color-red-100);
|
||||||
|
--background-success: var(--color-green-100);
|
||||||
|
--background-info: var(--color-blue-100);
|
||||||
|
--background-warning: var(--color-yellow-100);
|
||||||
|
|
||||||
--text-placeholder: var(--dark-grey-45);
|
--border-default: var(--color-slate-600);
|
||||||
--text-prominent: var(--constant-white);
|
--border-input: var(--color-slate-600);
|
||||||
--text-standard: var(--dark-grey-90);
|
--border-strong: var(--color-slate-200);
|
||||||
--text-standard-inverse: var(--grey-20);
|
--border-inverse: var(--color-white);
|
||||||
--text-subtle: var(--dark-grey-60);
|
--border-danger: var(--color-red-200);
|
||||||
--text-subtle-inverse: var(--grey-50);
|
--border-success: var(--color-green-200);
|
||||||
--text-prominent-inverse: var(--grey-20);
|
--border-warning: var(--color-yellow-200);
|
||||||
}
|
--border-info: var(--color-blue-200);
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
--text-default: var(--color-white);
|
||||||
background-color: var(--background-app);
|
--text-muted: var(--color-slate-300);
|
||||||
}
|
--text-inverse: var(--color-black);
|
||||||
|
--text-danger: var(--color-red-100);
|
||||||
|
--text-success: var(--color-green-100);
|
||||||
|
--text-warning: var(--color-yellow-100);
|
||||||
|
--text-info: var(--color-blue-100);
|
||||||
|
|
||||||
|
--ring: var(--border-strong);
|
||||||
|
|
||||||
|
--chart-1: #f6b44a;
|
||||||
|
--chart-2: #7585ff;
|
||||||
|
--chart-3: #d76a6a;
|
||||||
|
--chart-4: #d185e0;
|
||||||
|
--chart-5: #91cb80;
|
||||||
|
|
||||||
|
--sidebar: var(--background-default);
|
||||||
|
--sidebar-foreground: var(--text-default);
|
||||||
|
--sidebar-primary: var(--background-accent);
|
||||||
|
--sidebar-primary-foreground: var(--text-inverse);
|
||||||
|
--sidebar-accent: var(--background-muted);
|
||||||
|
--sidebar-accent-foreground: var(--text-default);
|
||||||
|
--sidebar-border: var(--border-default);
|
||||||
|
--sidebar-ring: var(--border-default);
|
||||||
|
}
|
||||||
|
|
||||||
|
@theme inline {
|
||||||
|
/* semantic */
|
||||||
|
--color-background-default: var(--background-default);
|
||||||
|
--color-background-medium: var(--background-medium);
|
||||||
|
--color-background-inverse: var(--background-inverse);
|
||||||
|
--color-background-muted: var(--background-muted);
|
||||||
|
--color-background-danger: var(--background-danger);
|
||||||
|
--color-background-success: var(--background-success);
|
||||||
|
--color-background-info: var(--background-info);
|
||||||
|
--color-background-warning: var(--background-warning);
|
||||||
|
|
||||||
|
--color-background-accent: var(--background-accent);
|
||||||
|
--color-border-accent: var(--border-accent);
|
||||||
|
--color-text-accent: var(--text-accent);
|
||||||
|
|
||||||
|
--color-border-default: var(--border-default);
|
||||||
|
--color-border-input: var(--border-input);
|
||||||
|
--color-border-strong: var(--border-strong);
|
||||||
|
--color-border-inverse: var(--border-inverse);
|
||||||
|
--color-border-danger: var(--border-danger);
|
||||||
|
--color-border-success: var(--border-success);
|
||||||
|
--color-border-warning: var(--border-warning);
|
||||||
|
--color-border-info: var(--border-info);
|
||||||
|
|
||||||
|
--color-text-default: var(--text);
|
||||||
|
--color-text-muted: var(--text-muted);
|
||||||
|
--color-text-inverse: var(--text-inverse);
|
||||||
|
--color-text-danger: var(--text-danger);
|
||||||
|
--color-text-success: var(--text-success);
|
||||||
|
--color-text-warning: var(--text-warning);
|
||||||
|
--color-text-info: var(--text-info);
|
||||||
|
|
||||||
|
/* fonts */
|
||||||
|
--font-sans: "Cash Sans", sans-serif;
|
||||||
|
--font-mono: "Cash Sans Mono", monospace;
|
||||||
|
--font-serif: serif;
|
||||||
|
|
||||||
|
/* shape */
|
||||||
|
--radius-sm: calc(var(--radius) - 4px);
|
||||||
|
--radius-md: calc(var(--radius) - 2px);
|
||||||
|
--radius-lg: var(--radius);
|
||||||
|
--radius-xl: calc(var(--radius) + 4px);
|
||||||
|
|
||||||
|
--color-ring: var(--ring);
|
||||||
|
|
||||||
|
--color-chart-1: var(--chart-1);
|
||||||
|
--color-chart-2: var(--chart-2);
|
||||||
|
--color-chart-3: var(--chart-3);
|
||||||
|
--color-chart-4: var(--chart-4);
|
||||||
|
--color-chart-5: var(--chart-5);
|
||||||
|
|
||||||
|
--color-sidebar: var(--sidebar);
|
||||||
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||||
|
--color-sidebar-primary: var(--sidebar-primary);
|
||||||
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||||
|
--color-sidebar-accent: var(--sidebar-accent);
|
||||||
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||||
|
--color-sidebar-border: var(--sidebar-border);
|
||||||
|
--color-sidebar-ring: var(--sidebar-ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Cash Sans';
|
font-family: "Cash Sans";
|
||||||
src:
|
src: url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff2/CashSans-Light.woff2)
|
||||||
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff2/CashSans-Regular.woff2)
|
format("woff2"),
|
||||||
format('woff2'),
|
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff/CashSans-Light.woff)
|
||||||
|
format("woff");
|
||||||
|
font-weight: 300;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Cash Sans";
|
||||||
|
src: url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff2/CashSans-Regular.woff2)
|
||||||
|
format("woff2"),
|
||||||
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff/CashSans-Regular.woff)
|
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff/CashSans-Regular.woff)
|
||||||
format('woff');
|
format("woff");
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Cash Sans';
|
font-family: "Cash Sans";
|
||||||
src:
|
src: url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff2/CashSans-Medium.woff2)
|
||||||
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff2/CashSans-Medium.woff2)
|
format("woff2"),
|
||||||
format('woff2'),
|
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff/CashSans-Medium.woff)
|
||||||
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff/CashSans-Medium.woff) format('woff');
|
format("woff");
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Cash Sans Mono';
|
font-family: "Cash Sans Mono";
|
||||||
src:
|
src: url(../assets/fonts/CashSansMono-Light.woff2) format("woff2");
|
||||||
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff2/CashSansMono-Regular.woff2)
|
font-weight: 300;
|
||||||
format('woff2'),
|
font-style: normal;
|
||||||
url(https://cash-f.squarecdn.com/static/fonts/cashsans/woff/CashSansMono-Regular.woff)
|
}
|
||||||
format('woff');
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Cash Sans Mono";
|
||||||
|
src: url(../assets/fonts/CashSansMono-Regular.woff2) format("woff2");
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border-default;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
@apply bg-background-default text-text-default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.titlebar-drag-region {
|
.titlebar-drag-region {
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -173,119 +263,3 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
|
||||||
--radius-sm: calc(var(--radius) - 4px);
|
|
||||||
--radius-md: calc(var(--radius) - 2px);
|
|
||||||
--radius-lg: var(--radius);
|
|
||||||
--radius-xl: calc(var(--radius) + 4px);
|
|
||||||
--color-background: var(--background);
|
|
||||||
--color-foreground: var(--foreground);
|
|
||||||
--color-card: var(--card);
|
|
||||||
--color-card-foreground: var(--card-foreground);
|
|
||||||
--color-popover: var(--popover);
|
|
||||||
--color-popover-foreground: var(--popover-foreground);
|
|
||||||
--color-primary: var(--primary);
|
|
||||||
--color-primary-foreground: var(--primary-foreground);
|
|
||||||
--color-secondary: var(--secondary);
|
|
||||||
--color-secondary-foreground: var(--secondary-foreground);
|
|
||||||
--color-muted: var(--muted);
|
|
||||||
--color-muted-foreground: var(--muted-foreground);
|
|
||||||
--color-accent: var(--accent);
|
|
||||||
--color-accent-foreground: var(--accent-foreground);
|
|
||||||
--color-destructive: var(--destructive);
|
|
||||||
--color-border: var(--border);
|
|
||||||
--color-input: var(--input);
|
|
||||||
--color-ring: var(--ring);
|
|
||||||
--color-chart-1: var(--chart-1);
|
|
||||||
--color-chart-2: var(--chart-2);
|
|
||||||
--color-chart-3: var(--chart-3);
|
|
||||||
--color-chart-4: var(--chart-4);
|
|
||||||
--color-chart-5: var(--chart-5);
|
|
||||||
--color-sidebar: var(--sidebar);
|
|
||||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
||||||
--color-sidebar-primary: var(--sidebar-primary);
|
|
||||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
||||||
--color-sidebar-accent: var(--sidebar-accent);
|
|
||||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
||||||
--color-sidebar-border: var(--sidebar-border);
|
|
||||||
--color-sidebar-ring: var(--sidebar-ring);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--radius: 0.625rem;
|
|
||||||
--background: oklch(1 0 0);
|
|
||||||
--foreground: oklch(0.145 0 0);
|
|
||||||
--card: oklch(1 0 0);
|
|
||||||
--card-foreground: oklch(0.145 0 0);
|
|
||||||
--popover: oklch(1 0 0);
|
|
||||||
--popover-foreground: oklch(0.145 0 0);
|
|
||||||
--primary: oklch(0.205 0 0);
|
|
||||||
--primary-foreground: oklch(0.985 0 0);
|
|
||||||
--secondary: oklch(0.97 0 0);
|
|
||||||
--secondary-foreground: oklch(0.205 0 0);
|
|
||||||
--muted: oklch(0.97 0 0);
|
|
||||||
--muted-foreground: oklch(0.556 0 0);
|
|
||||||
--accent: oklch(0.97 0 0);
|
|
||||||
--accent-foreground: oklch(0.205 0 0);
|
|
||||||
--destructive: oklch(0.577 0.245 27.325);
|
|
||||||
--border: oklch(0.922 0 0);
|
|
||||||
--input: oklch(0.922 0 0);
|
|
||||||
--ring: oklch(0.708 0 0);
|
|
||||||
--chart-1: oklch(0.646 0.222 41.116);
|
|
||||||
--chart-2: oklch(0.6 0.118 184.704);
|
|
||||||
--chart-3: oklch(0.398 0.07 227.392);
|
|
||||||
--chart-4: oklch(0.828 0.189 84.429);
|
|
||||||
--chart-5: oklch(0.769 0.188 70.08);
|
|
||||||
--sidebar: oklch(0.985 0 0);
|
|
||||||
--sidebar-foreground: oklch(0.145 0 0);
|
|
||||||
--sidebar-primary: oklch(0.205 0 0);
|
|
||||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
||||||
--sidebar-accent: oklch(0.97 0 0);
|
|
||||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
||||||
--sidebar-border: oklch(0.922 0 0);
|
|
||||||
--sidebar-ring: oklch(0.708 0 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
--background: oklch(0.145 0 0);
|
|
||||||
--foreground: oklch(0.985 0 0);
|
|
||||||
--card: oklch(0.205 0 0);
|
|
||||||
--card-foreground: oklch(0.985 0 0);
|
|
||||||
--popover: oklch(0.205 0 0);
|
|
||||||
--popover-foreground: oklch(0.985 0 0);
|
|
||||||
--primary: oklch(0.922 0 0);
|
|
||||||
--primary-foreground: oklch(0.205 0 0);
|
|
||||||
--secondary: oklch(0.269 0 0);
|
|
||||||
--secondary-foreground: oklch(0.985 0 0);
|
|
||||||
--muted: oklch(0.269 0 0);
|
|
||||||
--muted-foreground: oklch(0.708 0 0);
|
|
||||||
--accent: oklch(0.269 0 0);
|
|
||||||
--accent-foreground: oklch(0.985 0 0);
|
|
||||||
--destructive: oklch(0.704 0.191 22.216);
|
|
||||||
--border: oklch(1 0 0 / 10%);
|
|
||||||
--input: oklch(1 0 0 / 15%);
|
|
||||||
--ring: oklch(0.556 0 0);
|
|
||||||
--chart-1: oklch(0.488 0.243 264.376);
|
|
||||||
--chart-2: oklch(0.696 0.17 162.48);
|
|
||||||
--chart-3: oklch(0.769 0.188 70.08);
|
|
||||||
--chart-4: oklch(0.627 0.265 303.9);
|
|
||||||
--chart-5: oklch(0.645 0.246 16.439);
|
|
||||||
--sidebar: oklch(0.205 0 0);
|
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
|
||||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
||||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
||||||
--sidebar-accent: oklch(0.269 0 0);
|
|
||||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
||||||
--sidebar-border: oklch(1 0 0 / 10%);
|
|
||||||
--sidebar-ring: oklch(0.556 0 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer base {
|
|
||||||
* {
|
|
||||||
@apply border-border outline-ring/50;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
@apply bg-background text-foreground;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user