🧹 Chore/move v2 components to components dir (#6261)
* Removed old root UI components. * Fixed import path * Moved first v2 components to new components dir. * Changed icon to not import from root, since it somehow creates a recursive import * Removed irrelevant todo * Added docs for new components * Fixed type errors * Update packages/ui/components/index.ts Removing as per comment Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
This commit is contained in:
1 parent
aaac491dc7
commit
0cbaba73e4
47 files changed
+301
-449
No files matched your search
@@ -11,9 +11,7 @@ import { APP_NAME, COMPANY_NAME, SUPPORT_MAIL_ADDRESS } from "@calcom/lib/consta
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { App as AppType } from "@calcom/types/App";
|
||||
import { Button, Icon, Shell, showToast, SkeletonButton, SkeletonText } from "@calcom/ui";
|
||||
|
||||
import HeadSeo from "@components/seo/head-seo";
|
||||
import { Button, Icon, Shell, showToast, SkeletonButton, SkeletonText, HeadSeo } from "@calcom/ui";
|
||||
|
||||
const Component = ({
|
||||
name,
|
||||
|
||||
@@ -28,7 +28,7 @@ import { getRecurringFreq } from "@calcom/lib/recurringStrings";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { detectBrowserTimeFormat, setIs24hClockInLocalStorage, TimeFormat } from "@calcom/lib/timeFormat";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Icon } from "@calcom/ui";
|
||||
import { Icon, HeadSeo } from "@calcom/ui";
|
||||
|
||||
import { timeZone as localStorageTimeZone } from "@lib/clock";
|
||||
import useRouterQuery from "@lib/hooks/useRouterQuery";
|
||||
@@ -37,7 +37,6 @@ import Gates, { Gate, GateState } from "@components/Gates";
|
||||
import AvailableTimes from "@components/booking/AvailableTimes";
|
||||
import BookingDescription from "@components/booking/BookingDescription";
|
||||
import TimeOptions from "@components/booking/TimeOptions";
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
import PoweredByCal from "@components/ui/PoweredByCal";
|
||||
|
||||
import type { AvailabilityPageProps } from "../../../pages/[user]/[type]";
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import classNames from "classnames";
|
||||
|
||||
import { APP_NAME, LOGO } from "@calcom/lib/constants";
|
||||
import { Credits, HeadSeo } from "@calcom/ui";
|
||||
|
||||
import Loader from "@components/Loader";
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
|
||||
import Credits from "../../../../packages/ui/v2/core/Credits";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
|
||||
@@ -4,12 +4,10 @@ import { useRouter } from "next/router";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { COMPANY_NAME, DEVELOPER_DOCS, DOCS_URL, JOIN_SLACK, WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import { Icon } from "@calcom/ui";
|
||||
import { Icon, HeadSeo } from "@calcom/ui";
|
||||
|
||||
import { useLocale } from "@lib/hooks/useLocale";
|
||||
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
|
||||
import { ssgInit } from "@server/lib/ssg";
|
||||
|
||||
export default function Custom404() {
|
||||
|
||||
@@ -27,7 +27,7 @@ import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calco
|
||||
import prisma from "@calcom/prisma";
|
||||
import { baseEventTypeSelect } from "@calcom/prisma/selects";
|
||||
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
import { Icon } from "@calcom/ui";
|
||||
import { Icon, HeadSeo } from "@calcom/ui";
|
||||
|
||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
import { EmbedProps } from "@lib/withEmbedSsr";
|
||||
@@ -37,7 +37,6 @@ import { AvatarSSR } from "@components/ui/AvatarSSR";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
const HeadSeo = dynamic(() => import("@components/seo/head-seo"));
|
||||
export default function User(props: inferSSRProps<typeof getServerSideProps> & EmbedProps) {
|
||||
const { users, profile, eventTypes, isDynamicGroup, dynamicNames, dynamicUsernames, isSingleUser } = props;
|
||||
const [user] = users; //To be used when we only have a single user, not dynamic group
|
||||
|
||||
@@ -35,14 +35,13 @@ import { localStorage } from "@calcom/lib/webstorage";
|
||||
import prisma, { baseUserSelect } from "@calcom/prisma";
|
||||
import { Prisma } from "@calcom/prisma/client";
|
||||
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
import { Button, EmailInput, Icon } from "@calcom/ui";
|
||||
import { Button, EmailInput, Icon, HeadSeo } from "@calcom/ui";
|
||||
|
||||
import { timeZone } from "@lib/clock";
|
||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import CancelBooking from "@components/booking/CancelBooking";
|
||||
import EventReservationSchema from "@components/schemas/EventReservationSchema";
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ import { isSAMLLoginEnabled } from "@calcom/features/ee/sso/lib/saml";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { inferSSRProps } from "@calcom/types/inferSSRProps";
|
||||
import { Alert, Button, EmailField, PasswordField, TextField } from "@calcom/ui";
|
||||
import { HeadSeo } from "@calcom/web/components/seo/head-seo";
|
||||
import { Alert, Button, EmailField, PasswordField, TextField, HeadSeo } from "@calcom/ui";
|
||||
import { asStringOrNull } from "@calcom/web/lib/asStringOrNull";
|
||||
import { WEBAPP_URL } from "@calcom/web/lib/config/constants";
|
||||
import prisma from "@calcom/web/lib/prisma";
|
||||
|
||||
@@ -12,12 +12,11 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import useTheme from "@calcom/lib/hooks/useTheme";
|
||||
import { getTeamWithMembers } from "@calcom/lib/server/queries/teams";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { Avatar, Button, Icon } from "@calcom/ui";
|
||||
import { Avatar, Button, Icon, HeadSeo } from "@calcom/ui";
|
||||
|
||||
import { useToggleQuery } from "@lib/hooks/useToggleQuery";
|
||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
import Team from "@components/team/screens/Team";
|
||||
import AvatarGroup from "@components/ui/AvatarGroup";
|
||||
|
||||
|
||||
@@ -4,12 +4,10 @@ import dayjs from "@calcom/dayjs";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { detectBrowserTimeFormat } from "@calcom/lib/timeFormat";
|
||||
import prisma, { bookingMinimalSelect } from "@calcom/prisma";
|
||||
import { Button, Icon } from "@calcom/ui";
|
||||
import { Button, Icon, HeadSeo } from "@calcom/ui";
|
||||
|
||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
|
||||
export default function MeetingUnavailable(props: inferSSRProps<typeof getServerSideProps>) {
|
||||
const { t } = useLocale();
|
||||
|
||||
|
||||
@@ -5,9 +5,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { detectBrowserTimeFormat } from "@calcom/lib/timeFormat";
|
||||
import prisma, { bookingMinimalSelect } from "@calcom/prisma";
|
||||
import type { inferSSRProps } from "@calcom/types/inferSSRProps";
|
||||
import { Button, Icon } from "@calcom/ui";
|
||||
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
import { Button, Icon, HeadSeo } from "@calcom/ui";
|
||||
|
||||
export default function MeetingNotStarted(props: inferSSRProps<typeof getServerSideProps>) {
|
||||
const { t } = useLocale();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Button, Icon } from "@calcom/ui";
|
||||
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
import { Button, Icon, HeadSeo } from "@calcom/ui";
|
||||
|
||||
export default function NoMeetingFound() {
|
||||
const { t } = useLocale();
|
||||
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
AppUser,
|
||||
} from "@calcom/types/AppGetServerSideProps";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
Banner,
|
||||
Badge,
|
||||
ButtonGroup,
|
||||
Dialog,
|
||||
@@ -362,14 +362,14 @@ function SingleForm({ form, appUrl, Page }: SingleFormComponentProps) {
|
||||
</Button>
|
||||
</div>
|
||||
{!form._count?.responses && (
|
||||
<Banner
|
||||
className="mt-6"
|
||||
variant="neutral"
|
||||
title="No Responses yet"
|
||||
description="Wait for some time for responses to be collected. You can go and submit the form yourself as well."
|
||||
Icon={Icon.FiInfo}
|
||||
onDismiss={() => console.log("dismissed")}
|
||||
/>
|
||||
<>
|
||||
<Alert
|
||||
className="mt-6"
|
||||
severity="neutral"
|
||||
title="No responses yet"
|
||||
message="Wait for some time for responses to be collected. You can go and submit the form yourself as well."
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="w-full rounded-md border border-gray-200 p-8">
|
||||
|
||||
@@ -2,13 +2,18 @@ import { CheckCircleIcon, ExclamationIcon, InformationCircleIcon, XCircleIcon }
|
||||
import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { Icon } from "../icon";
|
||||
|
||||
export interface AlertProps {
|
||||
title?: ReactNode;
|
||||
// @TODO: Message should be children, more flexible?
|
||||
message?: ReactNode;
|
||||
// @TODO: Provide action buttons so style is always the same.
|
||||
actions?: ReactNode;
|
||||
className?: string;
|
||||
iconClassName?: string;
|
||||
severity: "success" | "warning" | "error" | "info";
|
||||
// @TODO: Success and info shouldn't exist as per design?
|
||||
severity: "success" | "warning" | "error" | "info" | "neutral";
|
||||
}
|
||||
export function Alert(props: AlertProps) {
|
||||
const { severity, iconClassName } = props;
|
||||
@@ -21,7 +26,8 @@ export function Alert(props: AlertProps) {
|
||||
severity === "error" && "border-red-900 bg-red-50 text-red-800",
|
||||
severity === "warning" && "border-yellow-700 bg-yellow-50 text-yellow-700",
|
||||
severity === "info" && "border-sky-700 bg-sky-50 text-sky-700",
|
||||
severity === "success" && "bg-gray-900 text-white"
|
||||
severity === "success" && "bg-gray-900 text-white",
|
||||
severity === "neutral" && "border-none bg-gray-100"
|
||||
)}>
|
||||
<div className="relative flex flex-col md:flex-row">
|
||||
<div className="flex-shrink-0">
|
||||
@@ -40,6 +46,9 @@ export function Alert(props: AlertProps) {
|
||||
aria-hidden="true"
|
||||
/>
|
||||
)}
|
||||
{severity === "neutral" && (
|
||||
<Icon.FiInfo className={classNames("h-5 w-5 text-gray-800", iconClassName)} aria-hidden="true" />
|
||||
)}
|
||||
{severity === "success" && (
|
||||
<CheckCircleIcon
|
||||
className={classNames("h-5 w-5 text-gray-400", iconClassName)}
|
||||
@@ -51,6 +60,7 @@ export function Alert(props: AlertProps) {
|
||||
<h3 className="text-sm font-medium">{props.title}</h3>
|
||||
<div className="text-sm">{props.message}</div>
|
||||
</div>
|
||||
{/* @TODO: Shouldn't be absolute. This makes it harder to give margin etc. */}
|
||||
{props.actions && <div className="absolute top-1 right-1 text-sm md:relative">{props.actions}</div>}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
|
||||
import { Examples, Example, Note, Title,CustomArgsTable,VariantsTable,VariantRow } from '@calcom/storybook/components'
|
||||
import { Icon } from "@calcom/ui";
|
||||
import {Alert} from './Alert';
|
||||
|
||||
<Meta title="UI/Alert" component={Alert} />
|
||||
|
||||
<Title title="Alert" suffix="Brief" subtitle="Version 2.0 — Last Update: 04 jan 2023"/>
|
||||
|
||||
## Definition
|
||||
Alerts provide time-based feedback to the user after taking an action.
|
||||
|
||||
## Structure
|
||||
Each alert has a state to represent neutral, positive or negative responses.
|
||||
|
||||
<CustomArgsTable of={Alert} />
|
||||
|
||||
<Examples title="Alert style">
|
||||
<Example title="Error">
|
||||
<Alert severity="error" title="Summarise what happened" message="Describe what can be done about it here." />
|
||||
</Example>
|
||||
<Example title="Warning">
|
||||
<Alert severity="warning" title="Summarise what happened" message="Describe what can be done about it here." />
|
||||
</Example>
|
||||
<Example title="With actions">
|
||||
<Alert
|
||||
severity="warning"
|
||||
title="Summarise what happened"
|
||||
message="Describe what can be done about it here."
|
||||
actions={<><button>Cancel me</button></>}
|
||||
/>
|
||||
</Example>
|
||||
</Examples>
|
||||
|
||||
<Title offset title="Alert" suffix="Variants" />
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Alert">
|
||||
<VariantsTable titles={['Default']} columnMinWidth={150}>
|
||||
<VariantRow variant="Success">
|
||||
<Alert severity="success" title="Summarise what happened" message="Describe what can be done about it here." />
|
||||
</VariantRow>
|
||||
<VariantRow variant="Warning">
|
||||
<Alert severity="warning" title="Summarise what happened" message="Describe what can be done about it here." />
|
||||
</VariantRow>
|
||||
<VariantRow variant="Error">
|
||||
<Alert severity="error" title="Summarise what happened" message="Describe what can be done about it here." />
|
||||
</VariantRow>
|
||||
<VariantRow variant="Neutral">
|
||||
<Alert severity="neutral" title="Summarise what happened" message="Describe what can be done about it here." />
|
||||
</VariantRow>
|
||||
</VariantsTable>
|
||||
</Story>
|
||||
</Canvas>
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Alert } from "./Alert";
|
||||
export type { AlertProps } from "./Alert";
|
||||
@@ -8,7 +8,7 @@ import type { AppFrontendPayload as App } from "@calcom/types/App";
|
||||
import type { CredentialFrontendPayload as Credential } from "@calcom/types/Credential";
|
||||
import { Icon } from "@calcom/ui";
|
||||
|
||||
import EmptyScreen from "../../v2/core/EmptyScreen";
|
||||
import { EmptyScreen } from "../empty-screen";
|
||||
import { AppCard } from "./AppCard";
|
||||
|
||||
export function useShouldShowArrows() {
|
||||
|
||||
@@ -2,5 +2,6 @@ export { useShouldShowArrows, AllApps } from "./AllApps";
|
||||
export { AppCard } from "./AppCard";
|
||||
export { Slider } from "./Slider";
|
||||
export { SkeletonLoader as AppSkeletonLoader } from "./SkeletonLoader";
|
||||
export { SkeletonLoader } from "./SkeletonLoader";
|
||||
export { TrendingAppsSlider } from "./TrendingAppsSlider";
|
||||
export { AppStoreCategories } from "./Categories";
|
||||
File renamed without changes.
@@ -0,0 +1,22 @@
|
||||
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
|
||||
import { Examples, Example, Note, Title,CustomArgsTable,VariantsTable,VariantRow } from '@calcom/storybook/components'
|
||||
import { Icon } from "@calcom/ui";
|
||||
import Credits from './Credits';
|
||||
|
||||
<Meta title="UI/Credits" component={Credits} />
|
||||
|
||||
<Title title="Credits" suffix="Brief" subtitle="Version 2.0 — Last Update: 05 jan 2023"/>
|
||||
|
||||
## Definition
|
||||
Shows the current copy right as well as app version name.
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Credits">
|
||||
<VariantsTable titles={[]} columnMinWidth={150}>
|
||||
<VariantRow variant="Default">
|
||||
<Credits />
|
||||
</VariantRow>
|
||||
</VariantsTable>
|
||||
</Story>
|
||||
</Canvas>
|
||||
@@ -0,0 +1 @@
|
||||
export { default as Credits } from "./Credits";
|
||||
+6
-1
@@ -1,6 +1,11 @@
|
||||
import { classNames } from "@calcom/lib";
|
||||
|
||||
export default function VerticalDivider({ className, ...props }: JSX.IntrinsicElements["svg"]) {
|
||||
export function Divider({ className, ...props }: JSX.IntrinsicElements["hr"]) {
|
||||
className = classNames(className, "gray-200");
|
||||
return <hr className={className} {...props} />;
|
||||
}
|
||||
|
||||
export function VerticalDivider({ className, ...props }: JSX.IntrinsicElements["svg"]) {
|
||||
className = classNames(className, "mx-3");
|
||||
return (
|
||||
<svg
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
|
||||
import { Examples, Example, Note, Title,CustomArgsTable,VariantsTable,VariantRow } from '@calcom/storybook/components'
|
||||
import { Icon } from "@calcom/ui";
|
||||
import {Divider, VerticalDivider} from './Divider';
|
||||
|
||||
<Meta title="UI/Divider" component={Divider} />
|
||||
|
||||
<Title title="Divider" suffix="Brief" subtitle="Version 2.0 — Last Update: 05 jan 2023"/>
|
||||
|
||||
## Definition
|
||||
Shows the current copy right as well as app version name.
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Divider">
|
||||
<VariantsTable titles={[]} columnMinWidth={150}>
|
||||
<VariantRow variant="Horizontal">
|
||||
<div className="dark:text-white">
|
||||
Text above
|
||||
<Divider />
|
||||
Text below
|
||||
</div>
|
||||
</VariantRow>
|
||||
<VariantRow variant="Vertical">
|
||||
<div className="flex dark:text-white">
|
||||
Text left
|
||||
<VerticalDivider />
|
||||
Text right
|
||||
</div>
|
||||
</VariantRow>
|
||||
</VariantsTable>
|
||||
</Story>
|
||||
</Canvas>
|
||||
@@ -0,0 +1 @@
|
||||
export { Divider, VerticalDivider } from "./Divider";
|
||||
+1
-1
@@ -5,7 +5,7 @@ import { SVGComponent } from "@calcom/types/SVGComponent";
|
||||
|
||||
import { Button } from "../../components/button";
|
||||
|
||||
export default function EmptyScreen({
|
||||
export function EmptyScreen({
|
||||
Icon,
|
||||
headline,
|
||||
description,
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
|
||||
import { Examples, Example, Note, Title,CustomArgsTable,VariantsTable,VariantRow } from '@calcom/storybook/components'
|
||||
import { Icon } from "@calcom/ui";
|
||||
import { EmptyScreen } from './EmptyScreen';
|
||||
|
||||
<Meta title="UI/EmptyScreen" component={EmptyScreen} />
|
||||
|
||||
<Title title="EmptyScreen" suffix="Brief" subtitle="Version 2.0 — Last Update: 05 jan 2023"/>
|
||||
|
||||
## Definition
|
||||
An empty state is where no info/ apps are added to a page with typically content. There must be a text that prompts users to learn more about why they see this state if necessary.
|
||||
The CTA button can prompt the user to add the info/ apps needed for the page.
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="EmptyScreen">
|
||||
<VariantsTable titles={[]} columnMinWidth={150}>
|
||||
<VariantRow variant="Default">
|
||||
<EmptyScreen
|
||||
Icon={Icon.FiCalendar}
|
||||
headline="Empty state header"
|
||||
description="Do consectetur qui ex deserunt do est veniam commodo. Eiusmod eiusmod dolore nostrud pariatur mollit sit commodo. Learn More."
|
||||
buttonText="Button text"
|
||||
/>
|
||||
</VariantRow>
|
||||
</VariantsTable>
|
||||
</Story>
|
||||
</Canvas>
|
||||
@@ -0,0 +1 @@
|
||||
export { EmptyScreen } from "./EmptyScreen";
|
||||
@@ -17,3 +17,5 @@ export {
|
||||
} from "./inputs/Input";
|
||||
export { Label } from "./inputs/Label";
|
||||
export { Select, SelectField, SelectWithValidation, getReactSelectProps } from "./select";
|
||||
export { TimezoneSelect } from "./timezone-select";
|
||||
export type { ITimezone, ITimezoneOption } from "./timezone-select";
|
||||
+2
-3
@@ -6,9 +6,9 @@ import BaseSelect, {
|
||||
Props as SelectProps,
|
||||
} from "react-timezone-select";
|
||||
|
||||
import { getReactSelectProps } from "../../components/form";
|
||||
import { getReactSelectProps } from "../select";
|
||||
|
||||
function TimezoneSelect({ className, components, ...props }: SelectProps) {
|
||||
export function TimezoneSelect({ className, components, ...props }: SelectProps) {
|
||||
const reactSelectProps = useMemo(() => {
|
||||
return getReactSelectProps({ className, components: components || {} });
|
||||
}, [className, components]);
|
||||
@@ -25,5 +25,4 @@ function TimezoneSelect({ className, components, ...props }: SelectProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export default TimezoneSelect;
|
||||
export type { ITimezone, ITimezoneOption };
|
||||
@@ -0,0 +1,2 @@
|
||||
export { TimezoneSelect } from "./TimezoneSelect";
|
||||
export type { ITimezone, ITimezoneOption } from "./TimezoneSelect";
|
||||
@@ -10,10 +10,9 @@ import {
|
||||
} from "@calcom/lib/OgImages";
|
||||
import { getBrowserInfo } from "@calcom/lib/browser/browser.utils";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { seoConfig, getSeoImage } from "@calcom/lib/next-seo.config";
|
||||
import { truncateOnWord } from "@calcom/lib/text";
|
||||
|
||||
import { getSeoImage, seoConfig } from "@lib/config/next-seo.config";
|
||||
|
||||
export type HeadSeoProps = {
|
||||
title: string;
|
||||
description: string;
|
||||
@@ -0,0 +1 @@
|
||||
export { HeadSeo } from "./HeadSeo";
|
||||
@@ -26,11 +26,14 @@ export {
|
||||
Select,
|
||||
SelectField,
|
||||
SelectWithValidation,
|
||||
TimezoneSelect,
|
||||
} from "./form";
|
||||
export type { ITimezone, ITimezoneOption } from "./form";
|
||||
export {
|
||||
AllApps,
|
||||
AppCard,
|
||||
AppSkeletonLoader,
|
||||
SkeletonLoader,
|
||||
Slider,
|
||||
TrendingAppsSlider,
|
||||
useShouldShowArrows,
|
||||
@@ -44,4 +47,12 @@ export type { ActionType } from "./table/TableActions";
|
||||
export { Icon } from "./icon";
|
||||
export { ErrorBoundary } from "./errorBoundary";
|
||||
export { Logo } from "./logo";
|
||||
export { Alert } from "./alert";
|
||||
export type { AlertProps } from "./alert";
|
||||
export { Credits } from "./credits";
|
||||
export { Divider, VerticalDivider } from "./divider";
|
||||
export { EmptyScreen } from "./empty-screen";
|
||||
export { List, ListItem, ListItemText, ListItemTitle, ListLinkItem } from "./list";
|
||||
export type { ListItemProps, ListProps } from "./list";
|
||||
export { HeadSeo } from "./head-seo";
|
||||
export { Skeleton, SkeletonAvatar, SkeletonButton, SkeletonContainer, SkeletonText } from "./skeleton";
|
||||
@@ -5,6 +5,8 @@ import classNames from "@calcom/lib/classNames";
|
||||
|
||||
export type ListProps = {
|
||||
roundContainer?: boolean;
|
||||
// @TODO: Do we still need this? Coming from old v2 component. Prefer to delete it :)
|
||||
noBorderTreatment?: boolean;
|
||||
} & JSX.IntrinsicElements["ul"];
|
||||
|
||||
export function List(props: ListProps) {
|
||||
@@ -15,6 +17,7 @@ export function List(props: ListProps) {
|
||||
"-mx-4 rounded-sm sm:mx-0 sm:overflow-hidden ",
|
||||
// Add rounded top and bottome if roundContainer is true
|
||||
props.roundContainer && "[&>*:first-child]:rounded-t-md [&>*:last-child]:rounded-b-md ",
|
||||
!props.noBorderTreatment && "divide-y divide-neutral-200 rounded-md border border-l border-r ",
|
||||
props.className
|
||||
)}>
|
||||
{props.children}
|
||||
@@ -56,6 +59,45 @@ export function ListItem(props: ListItemProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export type ListLinkItemProps = {
|
||||
href: string;
|
||||
heading: string;
|
||||
subHeading: string;
|
||||
disabled?: boolean;
|
||||
actions?: JSX.Element;
|
||||
} & JSX.IntrinsicElements["li"];
|
||||
|
||||
export function ListLinkItem(props: ListLinkItemProps) {
|
||||
const { href, heading = "", children, disabled = false, actions = <div /> } = props;
|
||||
let subHeading = props.subHeading;
|
||||
if (!subHeading) {
|
||||
subHeading = "";
|
||||
}
|
||||
return (
|
||||
<li
|
||||
className={classNames(
|
||||
"group flex w-full items-center justify-between p-5 hover:bg-neutral-50",
|
||||
disabled ? "hover:bg-white" : ""
|
||||
)}>
|
||||
<Link passHref href={href}>
|
||||
<a
|
||||
className={classNames(
|
||||
"flex-grow truncate text-sm",
|
||||
disabled ? "pointer-events-none cursor-not-allowed opacity-30" : ""
|
||||
)}>
|
||||
<h1 className="text-sm font-semibold leading-none">{heading}</h1>
|
||||
<h2 className="min-h-4 mt-2 text-sm font-normal leading-none">
|
||||
{subHeading.substring(0, 100)}
|
||||
{subHeading.length > 100 && "..."}
|
||||
</h2>
|
||||
<div className="mt-2">{children}</div>
|
||||
</a>
|
||||
</Link>
|
||||
{actions}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
export function ListItemTitle<TComponent extends keyof JSX.IntrinsicElements = "span">(
|
||||
props: JSX.IntrinsicElements[TComponent] & { component?: TComponent }
|
||||
) {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export { List, ListItem, ListItemText, ListItemTitle } from "./List";
|
||||
export { List, ListItem, ListItemText, ListItemTitle, ListLinkItem } from "./List";
|
||||
export type { ListItemProps, ListProps } from "./List";
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs';
|
||||
import { Examples, Example, Note, Title,CustomArgsTable,VariantsTable,VariantRow } from '@calcom/storybook/components'
|
||||
import { Icon } from "@calcom/ui";
|
||||
import { List, ListItem } from './List';
|
||||
|
||||
<Meta title="UI/List" component={List} />
|
||||
|
||||
<Title title="List" suffix="Brief" subtitle="Version 2.0 — Last Update: 05 jan 2023"/>
|
||||
|
||||
## Definition
|
||||
Sums it up nicely.
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="List">
|
||||
<VariantsTable titles={[]} columnMinWidth={150}>
|
||||
<VariantRow variant="Default">
|
||||
TODO!
|
||||
</VariantRow>
|
||||
</VariantsTable>
|
||||
</Story>
|
||||
</Canvas>
|
||||
@@ -6,7 +6,7 @@ import classNames from "@calcom/lib/classNames";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
import { Alert } from "../v2/core/Alert";
|
||||
import { Alert } from "../components/alert";
|
||||
import { showToast } from "../v2/core/notifications";
|
||||
|
||||
type InputProps = Omit<JSX.IntrinsicElements["input"], "name"> & { name: string };
|
||||
|
||||
+29
-21
@@ -8,10 +8,14 @@ export {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Checkbox,
|
||||
Credits,
|
||||
Divider,
|
||||
EmailField,
|
||||
EmailInput,
|
||||
EmptyScreen,
|
||||
FieldsetLegend,
|
||||
Form,
|
||||
HeadSeo,
|
||||
HintsOrErrors,
|
||||
Input,
|
||||
InputField,
|
||||
@@ -19,6 +23,11 @@ export {
|
||||
InputFieldWithSelect,
|
||||
InputLeading,
|
||||
Label,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
ListItemTitle,
|
||||
ListLinkItem,
|
||||
PasswordField,
|
||||
TextArea,
|
||||
TextAreaField,
|
||||
@@ -29,6 +38,8 @@ export {
|
||||
SelectField,
|
||||
SelectWithValidation,
|
||||
TableActions,
|
||||
TimezoneSelect,
|
||||
VerticalDivider,
|
||||
Skeleton,
|
||||
SkeletonAvatar,
|
||||
SkeletonText,
|
||||
@@ -37,16 +48,29 @@ export {
|
||||
DropdownActions,
|
||||
Icon,
|
||||
ErrorBoundary,
|
||||
Alert,
|
||||
TrendingAppsSlider,
|
||||
AppCard,
|
||||
AllApps,
|
||||
AppSkeletonLoader,
|
||||
SkeletonLoader,
|
||||
AppStoreCategories,
|
||||
Slider,
|
||||
useShouldShowArrows,
|
||||
} from "./components";
|
||||
export type { ActionType } from "./components";
|
||||
export type { AvatarProps, BadgeProps, ButtonBaseProps, ButtonProps, TopBannerProps } from "./components";
|
||||
export type {
|
||||
ActionType,
|
||||
AlertProps,
|
||||
AvatarProps,
|
||||
BadgeProps,
|
||||
ButtonBaseProps,
|
||||
ButtonProps,
|
||||
ITimezone,
|
||||
ITimezoneOption,
|
||||
ListItemProps,
|
||||
ListProps,
|
||||
TopBannerProps,
|
||||
} from "./components";
|
||||
export { default as CheckboxField } from "./components/form/checkbox/Checkbox";
|
||||
/** ⬇️ TODO - Move these to components */
|
||||
export { default as AddressInput } from "./form/AddressInputLazy";
|
||||
@@ -54,21 +78,10 @@ export { default as PhoneInput } from "./form/PhoneInputLazy";
|
||||
export { UnstyledSelect } from "./form/Select";
|
||||
export { default as Loader } from "./v2/core/Loader";
|
||||
export { default as TimezoneChangeDialog } from "./TimezoneChangeDialog";
|
||||
export {
|
||||
Alert,
|
||||
EmptyScreen,
|
||||
HorizontalTabs,
|
||||
SettingsToggle,
|
||||
showToast,
|
||||
Swatch,
|
||||
Switch,
|
||||
Card,
|
||||
VerticalTabs,
|
||||
} from "./v2";
|
||||
export type { AlertProps } from "./v2";
|
||||
export { Segment, SegmentOption } from "./v2/core";
|
||||
|
||||
export { HorizontalTabs, SettingsToggle, showToast, Swatch, Switch, Card, VerticalTabs } from "./v2";
|
||||
export { default as Shell, ShellMain, MobileNavigationMoreItems, ShellSubHeading } from "./v2/core/Shell";
|
||||
export { default as Banner } from "./v2/core/banner";
|
||||
|
||||
export { default as ColorPicker } from "./v2/core/colorpicker";
|
||||
export { default as ConfirmationDialogContent } from "./v2/core/ConfirmationDialogContent";
|
||||
export {
|
||||
@@ -80,7 +93,6 @@ export {
|
||||
DialogTrigger,
|
||||
} from "./v2/core/Dialog";
|
||||
export type { DialogProps } from "./v2/core/Dialog";
|
||||
export { default as Divider } from "./v2/core/Divider";
|
||||
export {
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
@@ -106,14 +118,10 @@ export { default as InstalledAppsLayout } from "./v2/core/layouts/InstalledAppsL
|
||||
export { default as SettingsLayout, getLayout as getSettingsLayout } from "./v2/core/layouts/SettingsLayout";
|
||||
export { default as WizardLayout, getLayout as getWizardLayout } from "./v2/core/layouts/WizardLayout";
|
||||
export { default as LinkIconButton } from "./v2/core/LinkIconButton";
|
||||
export { List, ListItem, ListItemText, ListItemTitle, ListLinkItem } from "./v2/core/List";
|
||||
export { default as MeetingTimeInTimezones } from "./v2/core/MeetingTimeInTimezones";
|
||||
export { default as Meta, MetaProvider } from "./v2/core/Meta";
|
||||
export { StepCard } from "./v2/core/StepCard";
|
||||
export { default as Stepper } from "./v2/core/Stepper";
|
||||
export { Steps } from "./v2/core/Steps";
|
||||
export { default as TimezoneSelect } from "./v2/core/TimezoneSelect";
|
||||
export type { ITimezone, ITimezoneOption } from "./v2/core/TimezoneSelect";
|
||||
export { Tooltip } from "./v2/core/Tooltip";
|
||||
export { default as VerticalDivider } from "./v2/core/VerticalDivider";
|
||||
export { default as WizardForm } from "./v2/core/WizardForm";
|
||||
@@ -1,6 +0,0 @@
|
||||
import { classNames } from "@calcom/lib";
|
||||
|
||||
export default function Divider({ className, ...props }: JSX.IntrinsicElements["hr"]) {
|
||||
className = classNames(className, "gray-200");
|
||||
return <hr className={className} {...props} />;
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
import Link from "next/link";
|
||||
import { createElement } from "react";
|
||||
|
||||
import classNames from "@calcom/lib/classNames";
|
||||
|
||||
export function List(props: JSX.IntrinsicElements["ul"] & { noBorderTreatment?: true }) {
|
||||
const { noBorderTreatment, ...rest } = props;
|
||||
return (
|
||||
<ul
|
||||
{...rest}
|
||||
className={classNames(
|
||||
"sm:mx-0 sm:overflow-hidden",
|
||||
!noBorderTreatment && "divide-y divide-neutral-200 rounded-md border border-l border-r ",
|
||||
props.className
|
||||
)}>
|
||||
{props.children}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
export type ListItemProps = { expanded?: boolean } & ({ href?: never } & JSX.IntrinsicElements["li"]);
|
||||
export type ListLinkItemProps = {
|
||||
href: string;
|
||||
heading: string;
|
||||
subHeading: string;
|
||||
disabled?: boolean;
|
||||
actions?: JSX.Element;
|
||||
} & JSX.IntrinsicElements["li"];
|
||||
|
||||
export function ListItem(props: ListItemProps) {
|
||||
const { href, expanded, ...passThroughProps } = props;
|
||||
|
||||
const elementType = href ? "a" : "li";
|
||||
|
||||
const element = createElement(
|
||||
elementType,
|
||||
{
|
||||
...passThroughProps,
|
||||
className: classNames(
|
||||
"items-center bg-white min-w-0 flex-1 flex border-gray-200",
|
||||
expanded ? "my-2 border" : "border -mb-px last:mb-0",
|
||||
props.className,
|
||||
(props.onClick || href) && "hover:bg-neutral-50"
|
||||
),
|
||||
},
|
||||
props.children
|
||||
);
|
||||
|
||||
return href ? (
|
||||
<Link passHref href={href}>
|
||||
{element}
|
||||
</Link>
|
||||
) : (
|
||||
element
|
||||
);
|
||||
}
|
||||
|
||||
export function ListLinkItem(props: ListLinkItemProps) {
|
||||
const { href, heading = "", children, disabled = false, actions = <div /> } = props;
|
||||
let subHeading = props.subHeading;
|
||||
if (!subHeading) {
|
||||
subHeading = "";
|
||||
}
|
||||
return (
|
||||
<li
|
||||
className={classNames(
|
||||
"group flex w-full items-center justify-between p-5 hover:bg-neutral-50",
|
||||
disabled ? "hover:bg-white" : ""
|
||||
)}>
|
||||
<Link passHref href={href}>
|
||||
<a
|
||||
className={classNames(
|
||||
"flex-grow truncate text-sm",
|
||||
disabled ? "pointer-events-none cursor-not-allowed opacity-30" : ""
|
||||
)}>
|
||||
<h1 className="text-sm font-semibold leading-none">{heading}</h1>
|
||||
<h2 className="min-h-4 mt-2 text-sm font-normal leading-none">
|
||||
{subHeading.substring(0, 100)}
|
||||
{subHeading.length > 100 && "..."}
|
||||
</h2>
|
||||
<div className="mt-2">{children}</div>
|
||||
</a>
|
||||
</Link>
|
||||
{actions}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
export function ListItemTitle<TComponent extends keyof JSX.IntrinsicElements = "span">(
|
||||
props: JSX.IntrinsicElements[TComponent] & { component?: TComponent }
|
||||
) {
|
||||
const { component = "span", ...passThroughProps } = props;
|
||||
|
||||
return createElement(
|
||||
component,
|
||||
{
|
||||
...passThroughProps,
|
||||
className: classNames("text-sm font-medium text-neutral-900 truncate", props.className),
|
||||
},
|
||||
props.children
|
||||
);
|
||||
}
|
||||
|
||||
export function ListItemText<TComponent extends keyof JSX.IntrinsicElements = "span">(
|
||||
props: JSX.IntrinsicElements[TComponent] & { component?: TComponent }
|
||||
) {
|
||||
const { component = "span", ...passThroughProps } = props;
|
||||
|
||||
return createElement(
|
||||
component,
|
||||
{
|
||||
...passThroughProps,
|
||||
className: classNames("text-sm text-gray-500 truncate", props.className),
|
||||
},
|
||||
props.children
|
||||
);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { Badge, BadgeProps } from "../../components/badge";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
description?: string;
|
||||
badgeText?: string;
|
||||
badgeVariant?: BadgeProps["variant"];
|
||||
infoIcon?: string;
|
||||
rightAlignedComponent?: ReactNode;
|
||||
};
|
||||
|
||||
function PageHeader({ title, description, rightAlignedComponent, badgeText, badgeVariant }: Props) {
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<div className="mr-4 flex-col">
|
||||
<div className="flex w-full items-center space-x-2 rtl:space-x-reverse">
|
||||
<h1 className="font-cal text-xl font-semibold text-black">{title}</h1>
|
||||
{badgeText && badgeVariant && <Badge variant={badgeVariant}>{badgeText}</Badge>}
|
||||
</div>
|
||||
<h2 className="text-sm text-gray-600">{description}</h2>
|
||||
</div>
|
||||
<div className="ml-auto ">{rightAlignedComponent && rightAlignedComponent}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PageHeader;
|
||||
@@ -1,11 +0,0 @@
|
||||
import React, { Fragment, ReactNode } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
export const Portal = (props: { children: React.ReactNode }) => {
|
||||
const portalContainer = document.getElementById("Portal");
|
||||
|
||||
// This should never be the case as it lives in _document.tsx
|
||||
if (!portalContainer) return null;
|
||||
|
||||
return ReactDOM.createPortal(<Fragment>{props.children}</Fragment>, portalContainer);
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
import * as RadioGroup from "@radix-ui/react-radio-group";
|
||||
import React from "react";
|
||||
|
||||
import { Label } from "../../components/form";
|
||||
|
||||
type SegmentProps = {
|
||||
label: string;
|
||||
children: React.ReactNode;
|
||||
} & RadioGroup.RadioGroupProps;
|
||||
|
||||
export function Segment({ label, children, ...rest }: SegmentProps) {
|
||||
return (
|
||||
<div>
|
||||
<div className="inline-flex flex-col">
|
||||
{label && <Label>{label}</Label>}
|
||||
<RadioGroup.Root
|
||||
className="flex space-x-1 rounded-md border-gray-200 bg-white p-[2px] text-sm font-medium leading-5 "
|
||||
{...rest}>
|
||||
{children}
|
||||
</RadioGroup.Root>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
type SegmentOptionProps = { value: string; children: React.ReactNode } & RadioGroup.RadioGroupItemProps;
|
||||
export function SegmentOption({ value, children, ...rest }: SegmentOptionProps) {
|
||||
return (
|
||||
<RadioGroup.Item
|
||||
value={value}
|
||||
className="radix-disabled:opacity-40 radix-state-checked:bg-gray-200 radix-state-checked:hover:bg-gray-200 rounded-[4px] py-[6px] px-3 hover:bg-gray-100"
|
||||
{...rest}>
|
||||
{children}
|
||||
</RadioGroup.Item>
|
||||
);
|
||||
}
|
||||
@@ -35,11 +35,11 @@ import {
|
||||
TimezoneChangeDialog,
|
||||
} from "../..";
|
||||
import { Logo, ErrorBoundary } from "../../components";
|
||||
import { Credits } from "../../components/credits";
|
||||
import { HeadSeo } from "../../components/head-seo";
|
||||
import { Icon } from "../../components/icon";
|
||||
import { SkeletonText } from "../../components/skeleton";
|
||||
import Credits from "./Credits";
|
||||
import { KBarContent, KBarRoot, KBarTrigger } from "./Kbar";
|
||||
import HeadSeo from "./head-seo";
|
||||
|
||||
/* TODO: Migate this */
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import { MouseEvent, useState } from "react";
|
||||
|
||||
import classNames from "@calcom/lib/classNames";
|
||||
import { SVGComponent } from "@calcom/types/SVGComponent";
|
||||
|
||||
const stylesByVariant = {
|
||||
neutral: { background: "bg-gray-100 ", text: "!text-gray-800", hover: "hover:!bg-gray-200" },
|
||||
warning: { background: "bg-orange-100 ", text: "!text-orange-800", hover: "hover:!bg-orange-200" },
|
||||
error: { background: "bg-red-100 ", text: "!text-red-800", hover: "hover:!bg-red-200" },
|
||||
};
|
||||
|
||||
export type BannerProps = {
|
||||
title: string;
|
||||
description?: string;
|
||||
variant: keyof typeof stylesByVariant;
|
||||
errorMessage?: string;
|
||||
Icon?: SVGComponent;
|
||||
onDismiss: (event: MouseEvent<HTMLElement, globalThis.MouseEvent>) => void;
|
||||
onAction?: (event: MouseEvent<HTMLElement, globalThis.MouseEvent>) => void;
|
||||
actionText?: string;
|
||||
} & JSX.IntrinsicElements["div"];
|
||||
|
||||
const Banner = (props: BannerProps) => {
|
||||
const { variant, errorMessage, title, description, className, Icon, ...rest } = props;
|
||||
const [show, setShow] = useState(true);
|
||||
if (!show) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"flex items-center rounded-md px-4 py-4",
|
||||
stylesByVariant[variant].background,
|
||||
stylesByVariant[variant].text,
|
||||
className
|
||||
)}
|
||||
{...rest}>
|
||||
<div className={classNames("flex flex-col text-sm")}>
|
||||
<div className="mb-2">{Icon && <Icon className="h-4 w-4" />}</div>
|
||||
<div className="flex flex-col space-y-2">
|
||||
<h1 className="font-semibold leading-none">{title}</h1>
|
||||
{description && <h2 className="font-normal leading-4">{description}</h2>}
|
||||
{props.variant === "error" && <p className="ml-4 pt-2 font-mono text-xs">{errorMessage}</p>}
|
||||
</div>
|
||||
<div className="mt-4 flex w-full items-center gap-4 self-start text-sm font-medium">
|
||||
{props.actionText && (
|
||||
<button className="text-sm font-medium leading-4" onClick={() => props.onAction}>
|
||||
Action
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="text-sm font-medium leading-4"
|
||||
onClick={(e) => {
|
||||
setShow(false);
|
||||
props.onDismiss(e);
|
||||
}}>
|
||||
Dismiss
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Banner;
|
||||
@@ -4,7 +4,7 @@ import { classNames } from "@calcom/lib";
|
||||
|
||||
import { Icon } from "../../..";
|
||||
import { Badge, BadgeProps } from "../../../components";
|
||||
import Divider from "../Divider";
|
||||
import { Divider } from "../../../components/divider";
|
||||
|
||||
type Action = { check: () => boolean; fn: () => void };
|
||||
export default function FormCard({
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
import merge from "lodash/merge";
|
||||
import { NextSeo, NextSeoProps } from "next-seo";
|
||||
|
||||
import { constructAppImage, constructGenericImage, constructMeetingImage } from "@calcom/lib/OgImages";
|
||||
import { getBrowserInfo } from "@calcom/lib/browser/browser.utils";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { seoConfig, getSeoImage, HeadSeoProps } from "@calcom/lib/next-seo.config";
|
||||
import { truncateOnWord } from "@calcom/lib/text";
|
||||
|
||||
/**
|
||||
* Build full seo tags from title, desc, canonical and url
|
||||
*/
|
||||
const buildSeoMeta = (pageProps: {
|
||||
title: string;
|
||||
description: string;
|
||||
image: string;
|
||||
siteName?: string;
|
||||
url?: string;
|
||||
canonical?: string;
|
||||
}): NextSeoProps => {
|
||||
const { title, description, image, canonical, siteName = seoConfig.headSeo.siteName } = pageProps;
|
||||
return {
|
||||
title: title,
|
||||
canonical: canonical,
|
||||
openGraph: {
|
||||
site_name: siteName,
|
||||
type: "website",
|
||||
title: title,
|
||||
description: description,
|
||||
images: [
|
||||
{
|
||||
url: image,
|
||||
},
|
||||
],
|
||||
},
|
||||
additionalMetaTags: [
|
||||
{
|
||||
property: "name",
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: "description",
|
||||
content: description,
|
||||
},
|
||||
{
|
||||
name: "description",
|
||||
content: description,
|
||||
},
|
||||
{
|
||||
property: "image",
|
||||
content: image,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
export const HeadSeo = (props: HeadSeoProps): JSX.Element => {
|
||||
const defaultUrl = getBrowserInfo()?.url;
|
||||
|
||||
const { title, description, siteName, canonical = defaultUrl, nextSeoProps = {}, app, meeting } = props;
|
||||
|
||||
const image = getSeoImage("ogImage") + constructGenericImage({ title, description });
|
||||
const truncatedDescription = truncateOnWord(description, 158);
|
||||
|
||||
const pageTitle = title + " | " + APP_NAME;
|
||||
let seoObject = buildSeoMeta({
|
||||
title: pageTitle,
|
||||
image,
|
||||
description: truncatedDescription,
|
||||
canonical,
|
||||
siteName,
|
||||
});
|
||||
|
||||
if (meeting) {
|
||||
const pageImage = getSeoImage("ogImage") + constructMeetingImage(meeting);
|
||||
seoObject = buildSeoMeta({
|
||||
title: pageTitle,
|
||||
description: truncatedDescription,
|
||||
image: pageImage,
|
||||
canonical,
|
||||
siteName,
|
||||
});
|
||||
}
|
||||
|
||||
if (app) {
|
||||
const pageImage =
|
||||
getSeoImage("ogImage") + constructAppImage({ ...app, description: truncatedDescription });
|
||||
seoObject = buildSeoMeta({
|
||||
title: pageTitle,
|
||||
description: truncatedDescription,
|
||||
image: pageImage,
|
||||
canonical,
|
||||
siteName,
|
||||
});
|
||||
}
|
||||
|
||||
const seoProps: NextSeoProps = merge(nextSeoProps, seoObject);
|
||||
|
||||
return <NextSeo {...seoProps} />;
|
||||
};
|
||||
|
||||
export default HeadSeo;
|
||||
@@ -1,6 +1,3 @@
|
||||
export { Alert } from "./Alert";
|
||||
export type { AlertProps } from "./Alert";
|
||||
export { default as Banner } from "./banner";
|
||||
export { Card } from "./Card";
|
||||
export type { BaseCardProps } from "./Card";
|
||||
export { default as ColorPicker } from "./colorpicker";
|
||||
@@ -22,11 +19,8 @@ export {
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuTriggerItem,
|
||||
} from "./Dropdown";
|
||||
export { default as EmptyScreen } from "./EmptyScreen";
|
||||
export { Checkbox, DatePicker, FormStep, Radio, RadioGroup } from "./form";
|
||||
export { default as LinkIconButton } from "./LinkIconButton";
|
||||
export { List, ListItem } from "./List";
|
||||
export type { ListItemProps } from "./List";
|
||||
export { default as Loader } from "./Loader";
|
||||
export { default as MeetingTimeInTimezones } from "./MeetingTimeInTimezones";
|
||||
export type { HorizontalTabItemProps } from "./navigation/tabs/HorizontalTabItem";
|
||||
@@ -34,14 +28,10 @@ export { default as HorizontalTabs, HorizontalTabItem } from "./navigation/tabs/
|
||||
export type { VerticalTabItemProps } from "./navigation/tabs/VerticalTabItem";
|
||||
export { default as VerticalTabs, VerticalTabItem } from "./navigation/tabs/VerticalTabs";
|
||||
export { default as showToast } from "./notifications";
|
||||
export { default as PageHeader } from "./PageHeader";
|
||||
export { Portal } from "./Portal";
|
||||
export { Segment, SegmentOption } from "./Segment";
|
||||
export { default as SettingsToggle } from "./SettingsToggle";
|
||||
export { default as Shell } from "./Shell";
|
||||
export { default as Stepper } from "./Stepper";
|
||||
export { default as Swatch } from "./Swatch";
|
||||
export { default as Switch } from "./Switch";
|
||||
export { default as Tooltip } from "./Tooltip";
|
||||
export { default as VerticalDivider } from "./VerticalDivider";
|
||||
export { default as WizardForm } from "./WizardForm";
|
||||
Reference in new issue
Block a user