client/web: adjust colors and some UI margins

Updates #10261

Signed-off-by: Sonia Appasamy <sonia@tailscale.com>
pull/10432/head
Sonia Appasamy 12 months ago committed by Sonia Appasamy
parent b155c7a091
commit 7d61b827e8

@ -102,14 +102,17 @@ function Header({
auth: AuthResponse auth: AuthResponse
newSession: () => Promise<void> newSession: () => Promise<void>
}) { }) {
const [loc] = useLocation() const [loc, setLocation] = useLocation()
return ( return (
<> <>
<div className="flex justify-between mb-12"> <div className="flex justify-between mb-12">
<div className="flex gap-3"> <div className="flex gap-3">
<TailscaleIcon /> <TailscaleIcon
<div className="inline text-neutral-800 text-lg font-medium leading-snug"> className="cursor-pointer"
onClick={() => setLocation("/")}
/>
<div className="inline text-gray-800 text-lg font-medium leading-snug">
{node.DomainName} {node.DomainName}
</div> </div>
</div> </div>
@ -118,7 +121,7 @@ function Header({
{loc !== "/" && loc !== "/update" && ( {loc !== "/" && loc !== "/update" && (
<Link <Link
to="/" to="/"
className="text-indigo-500 font-medium leading-snug block mb-[10px]" className="text-blue-500 font-medium leading-snug block mb-[10px]"
> >
&larr; Back to {node.DeviceName} &larr; Back to {node.DeviceName}
</Link> </Link>

@ -78,7 +78,7 @@ export default function ExitNodeSelector({
{ {
"border-gray-200": none, "border-gray-200": none,
"bg-amber-600 border-amber-600": advertising, "bg-amber-600 border-amber-600": advertising,
"bg-indigo-500 border-indigo-500": using, "bg-blue-500 border-blue-500": using,
}, },
className className
)} )}
@ -87,7 +87,7 @@ export default function ExitNodeSelector({
className={cx("flex-1 px-2 py-1.5 rounded-[1px]", { className={cx("flex-1 px-2 py-1.5 rounded-[1px]", {
"bg-white hover:bg-stone-100": none, "bg-white hover:bg-stone-100": none,
"bg-amber-600 hover:bg-orange-400": advertising, "bg-amber-600 hover:bg-orange-400": advertising,
"bg-indigo-500 hover:bg-indigo-400": using, "bg-blue-500 hover:bg-blue-400": using,
"cursor-not-allowed": disabled, "cursor-not-allowed": disabled,
})} })}
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}
@ -95,7 +95,7 @@ export default function ExitNodeSelector({
> >
<p <p
className={cx( className={cx(
"text-neutral-500 text-xs text-left font-medium uppercase tracking-wide mb-1", "text-gray-500 text-xs text-left font-medium uppercase tracking-wide mb-1",
{ "bg-opacity-70 text-white": advertising || using } { "bg-opacity-70 text-white": advertising || using }
)} )}
> >
@ -103,7 +103,7 @@ export default function ExitNodeSelector({
</p> </p>
<div className="flex items-center"> <div className="flex items-center">
<p <p
className={cx("text-neutral-800", { className={cx("text-gray-800", {
"text-white": advertising || using, "text-white": advertising || using,
})} })}
> >
@ -128,7 +128,7 @@ export default function ExitNodeSelector({
<button <button
className={cx("px-3 py-2 rounded-sm text-white", { className={cx("px-3 py-2 rounded-sm text-white", {
"bg-orange-400": advertising, "bg-orange-400": advertising,
"bg-indigo-400": using, "bg-blue-400": using,
"cursor-not-allowed": disabled, "cursor-not-allowed": disabled,
})} })}
onClick={(e) => { onClick={(e) => {
@ -213,7 +213,7 @@ function ExitNodeSelectorInner({
className="pb-1 mb-1 border-b last:border-b-0 last:mb-0" className="pb-1 mb-1 border-b last:border-b-0 last:mb-0"
> >
{group.name && ( {group.name && (
<div className="px-4 py-2 text-neutral-500 text-xs font-medium uppercase tracking-wide"> <div className="px-4 py-2 text-gray-500 text-xs font-medium uppercase tracking-wide">
{group.name} {group.name}
</div> </div>
)} )}

@ -143,7 +143,7 @@ function LoginPopoverContent({
{!auth.canManageNode && {!auth.canManageNode &&
(!auth.viewerIdentity || auth.authNeeded === AuthType.tailscale ? ( (!auth.viewerIdentity || auth.authNeeded === AuthType.tailscale ? (
<> <>
<p className="text-neutral-500 text-xs"> <p className="text-gray-500 text-xs">
{auth.viewerIdentity ? ( {auth.viewerIdentity ? (
<> <>
To make changes, sign in to confirm your identity. This extra To make changes, sign in to confirm your identity. This extra
@ -158,7 +158,7 @@ function LoginPopoverContent({
</p> </p>
<button <button
className={cx( className={cx(
"w-full px-3 py-2 bg-indigo-500 rounded shadow text-center text-white text-sm font-medium mt-2", "w-full px-3 py-2 bg-blue-500 rounded shadow text-center text-white text-sm font-medium mt-2",
{ {
"mb-2": auth.viewerIdentity, "mb-2": auth.viewerIdentity,
"cursor-not-allowed": !canConnectOverTS, "cursor-not-allowed": !canConnectOverTS,
@ -173,7 +173,7 @@ function LoginPopoverContent({
</button> </button>
</> </>
) : ( ) : (
<p className="text-neutral-500 text-xs"> <p className="text-gray-500 text-xs">
You dont have permission to make changes to this device, but you You dont have permission to make changes to this device, but you
can view most of its details. can view most of its details.
</p> </p>
@ -183,7 +183,7 @@ function LoginPopoverContent({
<hr className="my-2" /> <hr className="my-2" />
<div className="flex items-center"> <div className="flex items-center">
<User className="flex-shrink-0" /> <User className="flex-shrink-0" />
<p className="text-neutral-500 text-xs ml-2"> <p className="text-gray-500 text-xs ml-2">
We recognize you because you are accessing this page from{" "} We recognize you because you are accessing this page from{" "}
<span className="font-medium"> <span className="font-medium">
{auth.viewerIdentity.nodeName || auth.viewerIdentity.nodeIP} {auth.viewerIdentity.nodeName || auth.viewerIdentity.nodeIP}

@ -23,7 +23,7 @@ export default function DeviceDetailsView({
<> <>
<h1 className="mb-10">Device details</h1> <h1 className="mb-10">Device details</h1>
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
<div className="card"> <div className="-mx-5 card">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h1>{node.DeviceName}</h1> <h1>{node.DeviceName}</h1>
@ -36,7 +36,7 @@ export default function DeviceDetailsView({
</div> </div>
<button <button
className={cx( className={cx(
"px-3 py-2 bg-stone-50 rounded shadow border border-stone-200 text-neutral-800 text-sm font-medium", "px-3 py-2 bg-stone-50 rounded shadow border border-stone-200 text-gray-800 text-sm font-medium",
{ "cursor-not-allowed": readonly } { "cursor-not-allowed": readonly }
)} )}
onClick={() => onClick={() =>
@ -55,7 +55,7 @@ export default function DeviceDetailsView({
!readonly && ( !readonly && (
<UpdateAvailableNotification details={node.ClientVersion} /> <UpdateAvailableNotification details={node.ClientVersion} />
)} )}
<div className="card"> <div className="-mx-5 card">
<h2 className="mb-2">General</h2> <h2 className="mb-2">General</h2>
<table> <table>
<tbody> <tbody>
@ -95,7 +95,7 @@ export default function DeviceDetailsView({
</tbody> </tbody>
</table> </table>
</div> </div>
<div className="card"> <div className="-mx-5 card">
<h2 className="mb-2">Addresses</h2> <h2 className="mb-2">Addresses</h2>
<table> <table>
<tbody> <tbody>
@ -121,7 +121,7 @@ export default function DeviceDetailsView({
</table> </table>
</div> </div>
<Control.AdminContainer <Control.AdminContainer
className="text-neutral-500 text-sm leading-tight text-center" className="text-gray-500 text-sm leading-tight text-center"
node={node} node={node}
> >
Want even more details? Visit{" "} Want even more details? Visit{" "}

@ -28,12 +28,10 @@ export default function HomeView({
<div className="ml-3"> <div className="ml-3">
<h1>{node.DeviceName}</h1> <h1>{node.DeviceName}</h1>
{/* TODO(sonia): display actual status */} {/* TODO(sonia): display actual status */}
<p className="text-neutral-500 text-sm">Connected</p> <p className="text-gray-500 text-sm">Connected</p>
</div> </div>
</div> </div>
<p className="text-neutral-800 text-lg leading-[25.20px]"> <p className="text-gray-800 text-lg leading-[25.20px]">{node.IP}</p>
{node.IP}
</p>
</div> </div>
<ExitNodeSelector <ExitNodeSelector
className="mb-5" className="mb-5"
@ -41,10 +39,7 @@ export default function HomeView({
nodeUpdaters={nodeUpdaters} nodeUpdaters={nodeUpdaters}
disabled={readonly} disabled={readonly}
/> />
<Link <Link className="text-blue-500 font-medium leading-snug" to="/details">
className="text-indigo-500 font-medium leading-snug"
to="/details"
>
View device details &rarr; View device details &rarr;
</Link> </Link>
</div> </div>
@ -105,19 +100,19 @@ function SettingsCard({
> >
<div> <div>
<div className="flex gap-2"> <div className="flex gap-2">
<p className="text-neutral-800 font-medium leading-tight mb-2"> <p className="text-gray-800 font-medium leading-tight mb-2">
{title} {title}
</p> </p>
{badge && ( {badge && (
<div className="h-5 px-2 bg-stone-100 rounded-full flex items-center gap-2"> <div className="h-5 px-2 bg-stone-100 rounded-full flex items-center gap-2">
{badge.icon} {badge.icon}
<div className="text-neutral-500 text-xs font-medium"> <div className="text-gray-500 text-xs font-medium">
{badge.text} {badge.text}
</div> </div>
</div> </div>
)} )}
</div> </div>
<p className="text-neutral-500 text-sm leading-tight">{body}</p> <p className="text-gray-500 text-sm leading-tight">{body}</p>
</div> </div>
<div> <div>
<ArrowRight className="ml-3" /> <ArrowRight className="ml-3" />

@ -23,7 +23,7 @@ export default function SSHView({
your tailnet to SSH into it.{" "} your tailnet to SSH into it.{" "}
<a <a
href="https://tailscale.com/kb/1193/tailscale-ssh/" href="https://tailscale.com/kb/1193/tailscale-ssh/"
className="text-indigo-700" className="text-blue-700"
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
> >
@ -46,7 +46,7 @@ export default function SSHView({
</div> </div>
</div> </div>
<Control.AdminContainer <Control.AdminContainer
className="text-neutral-500 text-sm leading-tight" className="text-gray-500 text-sm leading-tight"
node={node} node={node}
> >
Remember to make sure that the{" "} Remember to make sure that the{" "}

@ -35,7 +35,7 @@ export default function SubnetRouterView({
Add devices to your tailnet without installing Tailscale.{" "} Add devices to your tailnet without installing Tailscale.{" "}
<a <a
href="https://tailscale.com/kb/1019/subnets/" href="https://tailscale.com/kb/1019/subnets/"
className="text-indigo-700" className="text-blue-700"
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
> >
@ -52,7 +52,7 @@ export default function SubnetRouterView({
value={inputText} value={inputText}
onChange={(e) => setInputText(e.target.value)} onChange={(e) => setInputText(e.target.value)}
/> />
<p className="my-2 h-6 text-neutral-500 text-sm leading-tight"> <p className="my-2 h-6 text-gray-500 text-sm leading-tight">
Add multiple routes by providing a comma-separated list. Add multiple routes by providing a comma-separated list.
</p> </p>
<Button <Button
@ -87,7 +87,7 @@ export default function SubnetRouterView({
className="flex justify-between items-center pb-2.5 mb-2.5 border-b border-b-gray-200 last:pb-0 last:mb-0 last:border-b-0" className="flex justify-between items-center pb-2.5 mb-2.5 border-b border-b-gray-200 last:pb-0 last:mb-0 last:border-b-0"
key={r.Route} key={r.Route}
> >
<div className="text-neutral-800 leading-snug">{r.Route}</div> <div className="text-gray-800 leading-snug">{r.Route}</div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
{r.Approved ? ( {r.Approved ? (
@ -100,7 +100,7 @@ export default function SubnetRouterView({
Approved Approved
</div> </div>
) : ( ) : (
<div className="text-neutral-500 text-sm leading-tight"> <div className="text-gray-500 text-sm leading-tight">
Pending approval Pending approval
</div> </div>
)} )}
@ -124,7 +124,7 @@ export default function SubnetRouterView({
))} ))}
</div> </div>
<Control.AdminContainer <Control.AdminContainer
className="mt-3 w-full text-center text-neutral-500 text-sm leading-tight" className="mt-3 w-full text-center text-gray-500 text-sm leading-tight"
node={node} node={node}
> >
To approve routes, in the admin console go to{" "} To approve routes, in the admin console go to{" "}
@ -135,7 +135,7 @@ export default function SubnetRouterView({
</Control.AdminContainer> </Control.AdminContainer>
</> </>
) : ( ) : (
<div className="px-5 py-4 bg-stone-50 rounded-lg border border-gray-200 text-center text-neutral-500"> <div className="px-5 py-4 bg-stone-50 rounded-lg border border-gray-200 text-center text-gray-500">
Not advertising any routes Not advertising any routes
</div> </div>
)} )}

@ -14,13 +14,154 @@
U+FFFD, U+E06B-E080, U+02E2, U+02E2, U+02B0, U+1D34, U+1D57, U+1D40, U+FFFD, U+E06B-E080, U+02E2, U+02E2, U+02B0, U+1D34, U+1D57, U+1D40,
U+207F, U+1D3A, U+1D48, U+1D30, U+02B3, U+1D3F; U+207F, U+1D3A, U+1D48, U+1D30, U+02B3, U+1D3F;
} }
html {
/**
* These lines force the page to occupy the full width of the browser,
* ignoring the scrollbar, and prevent horizontal scrolling. This eliminates
* shifting when moving between pages with a scrollbar and those without, by
* ignoring the width of the scrollbar.
*
* It also disables horizontal scrolling of the body wholesale, so, as always
* avoid content flowing off the page.
*/
width: 100vw;
overflow-x: hidden;
}
:root {
--color-white: 255 255 255;
--color-gray-0: 250 249 248;
--color-gray-50: 249 247 246;
--color-gray-100: 247 245 244;
--color-gray-200: 238 235 234;
--color-gray-300: 218 214 213;
--color-gray-400: 175 172 171;
--color-gray-500: 112 110 109;
--color-gray-600: 68 67 66;
--color-gray-700: 46 45 45;
--color-gray-800: 35 34 34;
--color-gray-900: 31 30 30;
--color-red-0: 255 246 244;
--color-red-50: 255 211 207;
--color-red-100: 255 177 171;
--color-red-200: 246 143 135;
--color-red-300: 228 108 99;
--color-red-400: 208 72 65;
--color-red-500: 178 45 48;
--color-red-600: 148 8 33;
--color-red-700: 118 0 18;
--color-red-800: 90 0 0;
--color-red-900: 66 0 0;
--color-yellow-0: 252 249 233;
--color-yellow-50: 248 229 185;
--color-yellow-100: 239 192 120;
--color-yellow-200: 229 153 62;
--color-yellow-300: 217 121 23;
--color-yellow-400: 187 85 4;
--color-yellow-500: 152 55 5;
--color-yellow-600: 118 43 11;
--color-yellow-700: 87 31 13;
--color-yellow-800: 58 22 7;
--color-yellow-900: 58 22 7;
--color-orange-0: 255 250 238;
--color-orange-50: 254 227 192;
--color-orange-100: 248 184 134;
--color-orange-200: 245 146 94;
--color-orange-300: 229 111 74;
--color-orange-400: 196 76 52;
--color-orange-500: 158 47 40;
--color-orange-600: 126 30 35;
--color-orange-700: 93 22 27;
--color-orange-800: 66 14 17;
--color-orange-900: 66 14 17;
--color-green-0: 239 255 237;
--color-green-50: 203 244 201;
--color-green-100: 133 217 150;
--color-green-200: 51 194 127;
--color-green-300: 30 166 114;
--color-green-400: 9 130 93;
--color-green-500: 14 98 69;
--color-green-600: 13 75 59;
--color-green-700: 11 55 51;
--color-green-800: 8 36 41;
--color-green-900: 8 36 41;
--color-blue-0: 240 245 255;
--color-blue-50: 206 222 253;
--color-blue-100: 173 199 252;
--color-blue-200: 133 170 245;
--color-blue-300: 108 148 236;
--color-blue-400: 90 130 222;
--color-blue-500: 75 112 204;
--color-blue-600: 63 93 179;
--color-blue-700: 50 73 148;
--color-blue-800: 37 53 112;
--color-blue-900: 25 34 74;
--color-text-base: rgb(var(--color-gray-800) / 1);
--color-text-muted: rgb(var(--color-gray-500) / 1);
--color-text-disabled: rgb(var(--color-gray-400) / 1);
--color-text-primary: rgb(var(--color-blue-600) / 1);
--color-text-warning: rgb(var(--color-orange-600) / 1);
--color-text-danger: rgb(var(--color-red-600) / 1);
--color-bg-app: rgb(var(--color-gray-100) / 1);
--color-bg-menu-item-hover: rgb(var(--color-gray-100) / 1);
--color-border-base: rgb(var(--color-gray-200) / 1);
}
html,
body,
#app-root {
min-height: 100vh;
}
body {
@apply text-text-base font-sans w-full antialiased;
font-size: 16px;
line-height: 1.4;
letter-spacing: -0.015em; /* Inter is a little loose by default */
text-rendering: optimizeLegibility;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
}
::selection {
background-color: rgba(97, 122, 255, 0.2);
}
strong {
@apply font-semibold;
}
button {
text-align: inherit; /* don't center buttons by default */
letter-spacing: inherit; /* inherit existing letter spacing, rather than using browser defaults */
vertical-align: top; /* fix alignment of display: inline-block buttons */
}
a:focus,
button:focus {
outline: none;
}
a:focus-visible,
button:focus-visible {
outline: auto;
}
h1 { h1 {
@apply text-neutral-800 text-[22px] font-medium leading-[30.80px]; @apply text-gray-800 text-[22px] font-medium leading-[30.80px];
} }
h2 { h2 {
@apply text-neutral-500 text-sm font-medium uppercase leading-tight tracking-wide; @apply text-gray-500 text-sm font-medium uppercase leading-tight tracking-wide;
} }
} }
@ -29,23 +170,23 @@
@apply p-5 bg-white rounded-lg border border-gray-200; @apply p-5 bg-white rounded-lg border border-gray-200;
} }
.card h1 { .card h1 {
@apply text-neutral-800 text-lg font-medium leading-snug; @apply text-gray-800 text-lg font-medium leading-snug;
} }
.card h2 { .card h2 {
@apply text-neutral-500 text-xs font-semibold uppercase tracking-wide; @apply text-gray-500 text-xs font-semibold uppercase tracking-wide;
} }
.card tbody { .card tbody {
@apply flex flex-col gap-2; @apply flex flex-col gap-2;
} }
.card td:first-child { .card td:first-child {
@apply w-40 text-neutral-500 text-sm leading-tight flex-shrink-0; @apply w-40 text-gray-500 text-sm leading-tight flex-shrink-0;
} }
.card td:last-child { .card td:last-child {
@apply text-neutral-800 text-sm leading-tight; @apply text-gray-800 text-sm leading-tight;
} }
.description { .description {
@apply text-neutral-500 leading-snug; @apply text-gray-500 leading-snug;
} }
/** /**
@ -53,21 +194,21 @@
* You can use the -large and -small modifiers for size variants. * You can use the -large and -small modifiers for size variants.
*/ */
.toggle { .toggle {
@apply appearance-none relative w-10 h-5 rounded-full bg-neutral-300 cursor-pointer; @apply appearance-none relative w-10 h-5 rounded-full bg-gray-300 cursor-pointer;
transition: background-color 200ms ease-in-out; transition: background-color 200ms ease-in-out;
} }
.toggle:disabled { .toggle:disabled {
@apply bg-neutral-200; @apply bg-gray-200;
@apply cursor-not-allowed; @apply cursor-not-allowed;
} }
.toggle:checked { .toggle:checked {
@apply bg-indigo-500; @apply bg-blue-500;
} }
.toggle:checked:disabled { .toggle:checked:disabled {
@apply bg-indigo-300; @apply bg-blue-300;
} }
.toggle:focus { .toggle:focus {
@ -86,7 +227,7 @@
} }
.toggle:checked:disabled::after { .toggle:checked:disabled::after {
@apply bg-indigo-50; @apply bg-blue-50;
} }
.toggle:enabled:active::after { .toggle:enabled:active::after {

@ -16,9 +16,9 @@ export default function Button(props: Props) {
className={cx( className={cx(
"px-3 py-2 rounded shadow justify-center items-center gap-2.5 inline-flex font-medium", "px-3 py-2 rounded shadow justify-center items-center gap-2.5 inline-flex font-medium",
{ {
"bg-indigo-500 text-white": intent === "primary" && !disabled, "bg-blue-500 text-white": intent === "primary" && !disabled,
"bg-indigo-400 text-indigo-200": intent === "primary" && disabled, "bg-blue-400 text-blue-200": intent === "primary" && disabled,
"bg-stone-50 shadow border border-stone-200 text-neutral-800": "bg-stone-50 shadow border border-stone-200 text-gray-800":
intent === "secondary", intent === "secondary",
"cursor-not-allowed": disabled, "cursor-not-allowed": disabled,
}, },

@ -0,0 +1,85 @@
{
"colors": {
"transparent": "transparent",
"current": "currentColor",
"white": "rgb(var(--color-white) / <alpha-value>)",
"gray": {
"0": "rgb(var(--color-gray-0) / <alpha-value>)",
"50": "rgb(var(--color-gray-50) / <alpha-value>)",
"100": "rgb(var(--color-gray-100) / <alpha-value>)",
"200": "rgb(var(--color-gray-200) / <alpha-value>)",
"300": "rgb(var(--color-gray-300) / <alpha-value>)",
"400": "rgb(var(--color-gray-400) / <alpha-value>)",
"500": "rgb(var(--color-gray-500) / <alpha-value>)",
"600": "rgb(var(--color-gray-600) / <alpha-value>)",
"700": "rgb(var(--color-gray-700) / <alpha-value>)",
"800": "rgb(var(--color-gray-800) / <alpha-value>)",
"900": "rgb(var(--color-gray-900) / <alpha-value>)"
},
"blue": {
"0": "rgb(var(--color-blue-0) / <alpha-value>)",
"50": "rgb(var(--color-blue-50) / <alpha-value>)",
"100": "rgb(var(--color-blue-100) / <alpha-value>)",
"200": "rgb(var(--color-blue-200) / <alpha-value>)",
"300": "rgb(var(--color-blue-300) / <alpha-value>)",
"400": "rgb(var(--color-blue-400) / <alpha-value>)",
"500": "rgb(var(--color-blue-500) / <alpha-value>)",
"600": "rgb(var(--color-blue-600) / <alpha-value>)",
"700": "rgb(var(--color-blue-700) / <alpha-value>)",
"800": "rgb(var(--color-blue-800) / <alpha-value>)",
"900": "rgb(var(--color-blue-900) / <alpha-value>)"
},
"green": {
"0": "rgb(var(--color-green-0) / <alpha-value>)",
"50": "rgb(var(--color-green-50) / <alpha-value>)",
"100": "rgb(var(--color-green-100) / <alpha-value>)",
"200": "rgb(var(--color-green-200) / <alpha-value>)",
"300": "rgb(var(--color-green-300) / <alpha-value>)",
"400": "rgb(var(--color-green-400) / <alpha-value>)",
"500": "rgb(var(--color-green-500) / <alpha-value>)",
"600": "rgb(var(--color-green-600) / <alpha-value>)",
"700": "rgb(var(--color-green-700) / <alpha-value>)",
"800": "rgb(var(--color-green-800) / <alpha-value>)",
"900": "rgb(var(--color-green-900) / <alpha-value>)"
},
"red": {
"0": "rgb(var(--color-red-0) / <alpha-value>)",
"50": "rgb(var(--color-red-50) / <alpha-value>)",
"100": "rgb(var(--color-red-100) / <alpha-value>)",
"200": "rgb(var(--color-red-200) / <alpha-value>)",
"300": "rgb(var(--color-red-300) / <alpha-value>)",
"400": "rgb(var(--color-red-400) / <alpha-value>)",
"500": "rgb(var(--color-red-500) / <alpha-value>)",
"600": "rgb(var(--color-red-600) / <alpha-value>)",
"700": "rgb(var(--color-red-700) / <alpha-value>)",
"800": "rgb(var(--color-red-800) / <alpha-value>)",
"900": "rgb(var(--color-red-900) / <alpha-value>)"
},
"yellow": {
"0": "rgb(var(--color-yellow-0) / <alpha-value>)",
"50": "rgb(var(--color-yellow-50) / <alpha-value>)",
"100": "rgb(var(--color-yellow-100) / <alpha-value>)",
"200": "rgb(var(--color-yellow-200) / <alpha-value>)",
"300": "rgb(var(--color-yellow-300) / <alpha-value>)",
"400": "rgb(var(--color-yellow-400) / <alpha-value>)",
"500": "rgb(var(--color-yellow-500) / <alpha-value>)",
"600": "rgb(var(--color-yellow-600) / <alpha-value>)",
"700": "rgb(var(--color-yellow-700) / <alpha-value>)",
"800": "rgb(var(--color-yellow-800) / <alpha-value>)",
"900": "rgb(var(--color-yellow-900) / <alpha-value>)"
},
"orange": {
"0": "rgb(var(--color-orange-0) / <alpha-value>)",
"50": "rgb(var(--color-orange-50) / <alpha-value>)",
"100": "rgb(var(--color-orange-100) / <alpha-value>)",
"200": "rgb(var(--color-orange-200) / <alpha-value>)",
"300": "rgb(var(--color-orange-300) / <alpha-value>)",
"400": "rgb(var(--color-orange-400) / <alpha-value>)",
"500": "rgb(var(--color-orange-500) / <alpha-value>)",
"600": "rgb(var(--color-orange-600) / <alpha-value>)",
"700": "rgb(var(--color-orange-700) / <alpha-value>)",
"800": "rgb(var(--color-orange-800) / <alpha-value>)",
"900": "rgb(var(--color-orange-900) / <alpha-value>)"
}
}
}

@ -1,9 +1,13 @@
const plugin = require("tailwindcss/plugin") const plugin = require("tailwindcss/plugin")
const styles = require("./styles.json")
/** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: { theme: {
screens: {
sm: "420px",
md: "768px",
lg: "1024px",
},
fontFamily: { fontFamily: {
sans: [ sans: [
"Inter", "Inter",
@ -29,8 +33,66 @@ module.exports = {
semibold: "600", semibold: "600",
bold: "700", bold: "700",
}, },
extend: {}, colors: styles.colors,
extend: {
colors: {
...styles.colors,
"bg-app": "var(--color-bg-app)",
"bg-menu-item-hover": "var(--color-bg-menu-item-hover)",
"border-base": "var(--color-border-base)",
"text-base": "var(--color-text-base)",
"text-muted": "var(--color-text-muted)",
"text-disabled": "var(--color-text-disabled)",
"text-primary": "var(--color-text-primary)",
"text-warning": "var(--color-text-warning)",
"text-danger": "var(--color-text-danger)",
},
borderColor: {
DEFAULT: "var(--color-border-base)",
},
boxShadow: {
dialog: "0 10px 40px rgba(0,0,0,0.12), 0 0 16px rgba(0,0,0,0.08)",
form: "0 1px 1px rgba(0, 0, 0, 0.04)",
soft: "0 4px 12px 0 rgba(0, 0, 0, 0.03)",
popover:
"0 0 0 1px rgba(136, 152, 170, 0.1), 0 15px 35px 0 rgba(49, 49, 93, 0.1), 0 5px 15px 0 rgba(0, 0, 0, 0.08)",
},
animation: {
"scale-in": "scale-in 120ms cubic-bezier(0.16, 1, 0.3, 1)",
"scale-out": "scale-out 120ms cubic-bezier(0.16, 1, 0.3, 1)",
},
transformOrigin: {
"radix-hovercard": "var(--radix-hover-card-content-transform-origin)",
"radix-popover": "var(--radix-popover-content-transform-origin)",
"radix-tooltip": "var(--radix-tooltip-content-transform-origin)",
},
keyframes: {
"scale-in": {
"0%": {
transform: "scale(0.94)",
opacity: "0",
},
"100%": {
transform: "scale(1)",
opacity: "1",
},
},
"scale-out": {
"0%": {
transform: "scale(1)",
opacity: "1",
},
"100%": {
transform: "scale(0.94)",
opacity: "0",
},
},
},
},
}, },
plugins: [ plugins: [
plugin(function ({ addVariant }) { plugin(function ({ addVariant }) {
addVariant("state-open", [ addVariant("state-open", [
@ -41,6 +103,13 @@ module.exports = {
'&[data-state="closed"]', '&[data-state="closed"]',
'[data-state="closed"] &', '[data-state="closed"] &',
]) ])
addVariant("state-delayed-open", [
'&[data-state="delayed-open"]',
'[data-state="delayed-open"] &',
])
addVariant("state-active", ['&[data-state="active"]'])
addVariant("state-inactive", ['&[data-state="inactive"]'])
}), }),
], ],
content: ["./src/**/*.html", "./src/**/*.{ts,tsx}", "./index.html"],
} }

Loading…
Cancel
Save