Feature/cal 677 brand color in settingsprofile (#1158)

* added CSS variable --brand-color

* added CustomBranding component

* prisma update for brand color

* added brandcolor to user context in viewer.me

* conflict resolution

* added brandColor input and mutation

* custom brand color to availability

* brandColor added to BookingPage

* fixed availability, booking for team and added customBranding to success

* brandColor added to cancel/uid

* requested changes

* lint fix

* further changes

* lint fix
pull/1141/head^2
Syed Ali Shahbaz 2021-11-16 14:21:46 +05:30 committed by GitHub
parent 11e7779a58
commit 4e01b13133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 94 additions and 29 deletions

View File

@ -0,0 +1,10 @@
import { useEffect } from "react";
const BrandColor = ({ val = "#292929" }: { val: string | undefined | null }) => {
useEffect(() => {
document.documentElement.style.setProperty("--brand-color", val);
}, [val]);
return null;
};
export default BrandColor;

View File

@ -23,6 +23,7 @@ import { useLocale } from "@lib/hooks/useLocale";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
import { trpc } from "@lib/trpc";
import CustomBranding from "@components/CustomBranding";
import Loader from "@components/Loader";
import { HeadSeo } from "@components/seo/head-seo";
import Avatar from "@components/ui/Avatar";
@ -166,6 +167,9 @@ export default function Shell(props: {
const pageTitle = typeof props.heading === "string" ? props.heading : props.title;
const query = useMeQuery();
const user = query.data;
const i18n = useViewerI18n();
if (i18n.status === "loading" || isRedirectingToOnboarding || loading) {
@ -178,6 +182,7 @@ export default function Shell(props: {
}
return (
<>
<CustomBranding val={user?.brandColor} />
<HeadSeo
title={pageTitle ?? "Cal.com"}
description={props.subtitle ? props.subtitle?.toString() : ""}

View File

@ -15,6 +15,7 @@ import useTheme from "@lib/hooks/useTheme";
import { isBrandingHidden } from "@lib/isBrandingHidden";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
import CustomBranding from "@components/CustomBranding";
import AvailableTimes from "@components/booking/AvailableTimes";
import DatePicker from "@components/booking/DatePicker";
import TimeOptions from "@components/booking/TimeOptions";
@ -95,6 +96,7 @@ const AvailabilityPage = ({ profile, eventType, workingHours }: Props) => {
name={profile.name}
avatar={profile.image}
/>
<CustomBranding val={profile.brandColor} />
<div>
<main
className={
@ -162,8 +164,8 @@ const AvailabilityPage = ({ profile, eventType, workingHours }: Props) => {
size={10}
truncateAfter={3}
/>
<h2 className="font-medium text-gray-500 dark:text-gray-300 mt-3">{profile.name}</h2>
<h1 className="font-cal mb-4 text-3xl font-semibold text-gray-800 dark:text-white">
<h2 className="mt-3 font-medium text-gray-500 dark:text-gray-300">{profile.name}</h2>
<h1 className="mb-4 text-3xl font-semibold text-gray-800 font-cal dark:text-white">
{eventType.title}
</h1>
<p className="px-2 py-1 mb-1 -ml-2 text-gray-500">

View File

@ -26,6 +26,7 @@ import { parseZone } from "@lib/parseZone";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
import { BookingCreateBody } from "@lib/types/booking";
import CustomBranding from "@components/CustomBranding";
import AvatarGroup from "@components/ui/AvatarGroup";
import { Button } from "@components/ui/Button";
import PhoneInput from "@components/ui/form/PhoneInput";
@ -200,7 +201,7 @@ const BookingPage = (props: BookingPageProps) => {
</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<CustomBranding val={props.profile.brandColor} />
<main className="max-w-3xl mx-auto my-0 rounded-sm sm:my-24 sm:border sm:dark:border-gray-600">
{isReady && (
<div className="overflow-hidden bg-white border border-gray-200 dark:bg-neutral-900 dark:border-0 sm:rounded-sm">

View File

@ -70,6 +70,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
weekStart: true,
availability: true,
hideBranding: true,
brandColor: true,
theme: true,
plan: true,
eventTypes: {
@ -192,6 +193,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
slug: user.username,
theme: user.theme,
weekStart: user.weekStart,
brandColor: user.brandColor,
},
date: dateParam,
eventType: eventTypeObject,

View File

@ -34,6 +34,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
bio: true,
avatar: true,
theme: true,
brandColor: true,
},
});
@ -108,6 +109,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
name: user.name,
image: user.avatar,
theme: user.theme,
brandColor: user.brandColor,
},
eventType: eventTypeObject,
booking,

View File

@ -9,6 +9,7 @@ import { useLocale } from "@lib/hooks/useLocale";
import prisma from "@lib/prisma";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
import CustomBranding from "@components/CustomBranding";
import { HeadSeo } from "@components/seo/head-seo";
import { Button } from "@components/ui/Button";
@ -64,6 +65,7 @@ export default function Type(props) {
title={`${t("cancel")} ${props.booking && props.booking.title} | ${props.profile.name}`}
description={`${t("cancel")} ${props.booking && props.booking.title} | ${props.profile.name}`}
/>
<CustomBranding val={props.profile.brandColor} />
<main className="max-w-3xl mx-auto my-24">
<div className="fixed inset-0 z-50 overflow-y-auto">
<div className="flex items-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
@ -159,6 +161,7 @@ export async function getServerSideProps(context) {
id: true,
username: true,
name: true,
brandColor: true,
},
},
eventType: {

View File

@ -136,6 +136,8 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const avatarRef = useRef<HTMLInputElement>(null!);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const brandColorRef = useRef<HTMLInputElement>(null!);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const hideBrandingRef = useRef<HTMLInputElement>(null!);
const [selectedTheme, setSelectedTheme] = useState<OptionTypeBase>();
const [selectedTimeZone, setSelectedTimeZone] = useState<ITimezone>(props.user.timeZone);
@ -166,6 +168,7 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
const enteredName = nameRef.current.value;
const enteredDescription = descriptionRef.current.value;
const enteredAvatar = avatarRef.current.value;
const enteredBrandColor = brandColorRef.current.value;
const enteredTimeZone = typeof selectedTimeZone === "string" ? selectedTimeZone : selectedTimeZone.value;
const enteredWeekStartDay = selectedWeekStartDay.value;
const enteredHideBranding = hideBrandingRef.current.checked;
@ -182,6 +185,7 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
weekStart: asStringOrUndefined(enteredWeekStartDay),
hideBranding: enteredHideBranding,
theme: asStringOrNull(selectedTheme?.value),
brandColor: enteredBrandColor,
locale: enteredLanguage,
});
}
@ -370,6 +374,23 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
</div>
</div>
</div>
<div>
<label htmlFor="brandColor" className="block text-sm font-medium text-gray-700">
{t("brand_color")}
</label>
<div className="flex mt-1">
<input
ref={brandColorRef}
type="text"
name="brandColor"
id="brandColor"
placeholder="#hex-code"
className="block w-full px-3 py-2 mt-1 border border-gray-300 rounded-sm shadow-sm focus:outline-none focus:ring-neutral-500 focus:border-neutral-500 sm:text-sm"
defaultValue={props.user.brandColor}
/>
</div>
<hr className="mt-6" />
</div>
<div>
<div className="relative flex items-start">
<div className="flex items-center h-5">
@ -434,6 +455,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
hideBranding: true,
theme: true,
plan: true,
brandColor: true,
},
});

View File

@ -18,6 +18,7 @@ import { isBrandingHidden } from "@lib/isBrandingHidden";
import prisma from "@lib/prisma";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import CustomBranding from "@components/CustomBranding";
import { HeadSeo } from "@components/seo/head-seo";
import Button from "@components/ui/Button";
@ -89,6 +90,7 @@ export default function Success(props: inferSSRProps<typeof getServerSideProps>)
title={needsConfirmation ? t("booking_submitted") : t("booking_confirmed")}
description={needsConfirmation ? t("booking_submitted") : t("booking_confirmed")}
/>
<CustomBranding val={props.profile.brandColor} />
<main className="max-w-3xl py-24 mx-auto">
<div className="fixed inset-0 z-50 overflow-y-auto">
<div className="flex items-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
@ -303,6 +305,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
hideBranding: true,
plan: true,
theme: true,
brandColor: true,
},
},
team: {
@ -330,6 +333,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
hideBranding: true,
plan: true,
theme: true,
brandColor: true,
},
});
if (user) {
@ -346,6 +350,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
const profile = {
name: eventType.team?.name || eventType.users[0]?.name || null,
theme: (!eventType.team?.name && eventType.users[0]?.theme) || null,
brandColor: eventType.team ? null : eventType.users[0].brandColor,
};
return {

View File

@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "users" ADD COLUMN "brandColor" TEXT NOT NULL DEFAULT E'#292929';
UPDATE "users" SET "brandColor" = '#292929';

View File

@ -94,6 +94,7 @@ model User {
plan UserPlan @default(PRO)
Schedule Schedule[]
webhooks Webhook[]
brandColor String @default("#292929")
@@map(name: "users")
}

View File

@ -438,6 +438,7 @@
"timezone": "Timezone",
"first_day_of_week": "First Day of Week",
"single_theme": "Single Theme",
"brand_color": "Brand Color",
"file_not_named": "File is not named [idOrSlug]/[user]",
"create_team": "Create Team",
"name": "Name",

View File

@ -43,6 +43,7 @@ async function getUserFromSession({
hideBranding: true,
avatar: true,
twoFactorEnabled: true,
brandColor: true,
credentials: {
select: {
id: true,

View File

@ -55,6 +55,7 @@ const loggedInViewerRouter = createProtectedRouter()
createdDate,
completedOnboarding,
twoFactorEnabled,
brandColor,
} = ctx.user;
const me = {
id,
@ -69,6 +70,7 @@ const loggedInViewerRouter = createProtectedRouter()
createdDate,
completedOnboarding,
twoFactorEnabled,
brandColor,
};
return me;
},
@ -444,6 +446,7 @@ const loggedInViewerRouter = createProtectedRouter()
timeZone: z.string().optional(),
weekStart: z.string().optional(),
hideBranding: z.boolean().optional(),
brandColor: z.string().optional(),
theme: z.string().optional().nullable(),
completedOnboarding: z.boolean().optional(),
locale: z.string().optional(),

View File

@ -2,9 +2,13 @@
@tailwind components;
@tailwind utilities;
:root {
--brand-color: #292929;
}
/* PhoneInput dark-mode overrides (it would add a lot of boilerplate to do this in JavaScript) */
.PhoneInputInput {
@apply text-sm focus:ring-0 border-0;
@apply text-sm border-0 focus:ring-0;
}
.dark .PhoneInputInput {
@apply bg-brand;
@ -32,23 +36,23 @@
}
.btn-sm.btn-primary {
@apply inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-sm shadow-sm text-white bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-3 py-2 text-sm font-medium leading-4 text-white border border-transparent rounded-sm shadow-sm bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn.btn-primary {
@apply inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-sm shadow-sm text-white bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-4 py-2 text-sm font-medium text-white border border-transparent rounded-sm shadow-sm bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-lg.btn-primary {
@apply inline-flex items-center px-4 py-2 border border-transparent text-base font-medium rounded-sm shadow-sm text-white bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-4 py-2 text-base font-medium text-white border border-transparent rounded-sm shadow-sm bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-xl.btn-primary {
@apply inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-sm shadow-sm text-white bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-6 py-3 text-base font-medium text-white border border-transparent rounded-sm shadow-sm bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-wide.btn-primary {
@apply w-full text-center px-4 py-2 border border-transparent text-sm font-medium rounded-sm shadow-sm text-white bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply w-full px-4 py-2 text-sm font-medium text-center text-white border border-transparent rounded-sm shadow-sm bg-neutral-900 hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
/* Secondary buttons */
@ -57,23 +61,23 @@
}
.btn-sm.btn-secondary {
@apply inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-3 py-2 text-sm font-medium leading-4 border border-transparent rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn.btn-secondary {
@apply inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-4 py-2 text-sm font-medium border border-transparent rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-lg.btn-secondary {
@apply inline-flex items-center px-4 py-2 border border-transparent text-base font-medium rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-4 py-2 text-base font-medium border border-transparent rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-xl.btn-secondary {
@apply inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-6 py-3 text-base font-medium border border-transparent rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-wide.btn-secondary {
@apply w-full text-center px-4 py-2 border border-transparent text-sm font-medium rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply w-full px-4 py-2 text-sm font-medium text-center border border-transparent rounded-sm text-neutral-700 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
/* White buttons */
@ -82,27 +86,27 @@
}
.btn-sm.btn-white {
@apply inline-flex items-center px-3 py-2 border border-gray-300 shadow-sm text-sm leading-4 font-medium rounded-sm text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-3 py-2 text-sm font-medium leading-4 text-gray-700 bg-white border border-gray-300 rounded-sm shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn.btn-white {
@apply inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-sm text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-sm shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-lg.btn-white {
@apply inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-base font-medium rounded-sm text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-4 py-2 text-base font-medium text-gray-700 bg-white border border-gray-300 rounded-sm shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-xl.btn-white {
@apply inline-flex items-center px-6 py-3 border border-gray-300 shadow-sm text-base font-medium rounded-sm text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-6 py-3 text-base font-medium text-gray-700 bg-white border border-gray-300 rounded-sm shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.btn-wide.btn-white {
@apply w-full text-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-sm text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply w-full px-4 py-2 text-sm font-medium text-center text-gray-700 bg-white border border-gray-300 rounded-sm shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
/* btn icon */
.btn-icon {
@apply p-2 border border-transparent hover:border-gray-300 cursor-pointer rounded-sm text-neutral-500 hover:text-neutral-900;
@apply p-2 border border-transparent rounded-sm cursor-pointer hover:border-gray-300 text-neutral-500 hover:text-neutral-900;
}
/* slider */
.slider {
@ -110,15 +114,15 @@
}
.slider > .slider-track {
@apply relative flex-grow h-1 bg-neutral-400 rounded-md;
@apply relative flex-grow h-1 rounded-md bg-neutral-400;
}
.slider .slider-range {
@apply absolute h-full bg-neutral-700 rounded-full;
@apply absolute h-full rounded-full bg-neutral-700;
}
.slider .slider-thumb {
@apply block w-3 h-3 bg-neutral-700 rounded-full shadow-sm cursor-pointer transition-all;
@apply block w-3 h-3 transition-all rounded-full shadow-sm cursor-pointer bg-neutral-700;
}
.slider .slider-thumb:hover {
@ -170,12 +174,12 @@
}
.react-multi-email > [type="text"] {
@apply shadow-sm dark:bg-gray-700 dark:text-white dark:border-gray-900 focus:ring-black focus:border-brand block w-full sm:text-sm border-gray-300 rounded-md;
@apply block w-full border-gray-300 rounded-md shadow-sm dark:bg-gray-700 dark:text-white dark:border-gray-900 focus:ring-black focus:border-brand sm:text-sm;
}
.react-multi-email [data-tag] {
box-shadow: none !important;
@apply inline-flex items-center px-2 py-1 my-1 mr-2 border border-transparent text-sm font-medium rounded-md text-gray-900 dark:text-white bg-neutral-200 hover:bg-neutral-100 dark:bg-brand focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-2 py-1 my-1 mr-2 text-sm font-medium text-gray-900 border border-transparent rounded-md dark:text-white bg-neutral-200 hover:bg-neutral-100 dark:bg-brand focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.react-multi-email > span[data-placeholder] {
@ -203,7 +207,7 @@
}
.react-multi-email [data-tag] {
@apply inline-flex items-center px-2 py-1 my-1 mr-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-gray-900 dark:text-white bg-neutral-200 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
@apply inline-flex items-center px-2 py-1 my-1 mr-2 text-sm font-medium text-gray-900 border border-transparent rounded-md shadow-sm dark:text-white bg-neutral-200 hover:bg-neutral-100 dark:bg-neutral-900 dark:hover:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-500;
}
.react-multi-email [data-tag] [data-tag-item] {
@ -332,11 +336,11 @@
}
nav#nav--settings > a {
@apply border-transparent text-gray-900 hover:bg-gray-50 hover:text-gray-900 border-l-4 px-3 py-2 flex items-center text-sm font-medium;
@apply flex items-center px-3 py-2 text-sm font-medium text-gray-900 border-l-4 border-transparent hover:bg-gray-50 hover:text-gray-900;
}
nav#nav--settings > a svg {
@apply text-gray-400 group-hover:text-gray-500 flex-shrink-0 -ml-1 mr-3 h-6 w-6;
@apply flex-shrink-0 w-6 h-6 mr-3 -ml-1 text-gray-400 group-hover:text-gray-500;
}
nav#nav--settings > a.active {

View File

@ -13,7 +13,7 @@ module.exports = {
extend: {
colors: {
/* your primary brand color */
brand: "#292929",
brand: "var(--brand-color)",
black: "#111111",
gray: {