Skip to content

Commit

Permalink
feat: Redesigned left side panel
Browse files Browse the repository at this point in the history
  • Loading branch information
areknawo committed May 29, 2024
1 parent ab1fe11 commit bb8d73a
Show file tree
Hide file tree
Showing 51 changed files with 672 additions and 781 deletions.
77 changes: 77 additions & 0 deletions apps/web/src/components/fragments/collapsible-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Component, JSX, Show, createSignal } from "solid-js";
import { mdiChevronDown } from "@mdi/js";
import clsx from "clsx";
import { Card, Heading, IconButton } from "#components/primitives";

interface CollapsibleSectionProps {
icon: JSX.Element;
label: string;
children?: JSX.Element;
action?: JSX.Element;
gradient?: boolean;
collapsible?: boolean;
defaultOpened?: boolean;
}

const CollapsibleSection: Component<CollapsibleSectionProps> = (props) => {
const [opened, setOpened] = createSignal(
typeof props.defaultOpened === "boolean" ? props.defaultOpened : true
);

return (
<div class="w-full flex flex-col m-0 p-0 items-start">
<div class="flex w-full gap-2 items-center">
<div class="flex-1 flex">
<button
class="group flex flex-1 justify-center items-center"
onClick={() => {
setOpened(!opened());
}}
>
<div class="opacity-90 w-full flex justify-center items-center p-0 m-0 pr-0.5 relative rounded-lg md:group-hover:bg-gray-200 md:dark:group-hover:bg-gray-700">
<Show when={typeof props.icon === "string"} fallback={props.icon}>
<IconButton
badge
path={props.icon as string}
text="base"
color={props.gradient ? "primary" : "base"}
class="m-0"
variant="text"
hover={false}
/>
</Show>
<Heading
level={3}
class={clsx(
"flex-1 text-start whitespace-nowrap mr-3",
props.gradient && "text-transparent bg-gradient-to-tr bg-clip-text"
)}
>
{props.label}
</Heading>
<IconButton
badge
path={mdiChevronDown}
text="soft"
class={clsx("m-0 h-7 w-7 p-0.5", !opened() && "rotate-90")}
variant="text"
/>
</div>
<div class="flex-1" />
</button>
</div>
{opened() && props.action}
</div>
<div
class={clsx(
"flex flex-col justify-center items-start gap-2 ml-3.5 pl-3.5 w-[calc(100%-0.875rem)] border-l-2 border-gray-200 dark:border-gray-700",
opened() ? "py-1 my-1" : "max-h-0 overflow-hidden"
)}
>
{props.children}
</div>
</div>
);
};

export { CollapsibleSection };
2 changes: 1 addition & 1 deletion apps/web/src/components/fragments/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ export * from "./mini-editor";
export * from "./input-field";
export * from "./svg-defs";
export * from "./scroll-shadow";
export * from "./titled-card";
export * from "./collapsible-section";
export * from "./searchable-select";
39 changes: 0 additions & 39 deletions apps/web/src/components/fragments/titled-card.tsx

This file was deleted.

7 changes: 3 additions & 4 deletions apps/web/src/ee/settings/billing/api-usage-card.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { mdiPoll } from "@mdi/js";
import { Button } from "@vrite/components";
import { Component, Show, createResource } from "solid-js";
import { TitledCard } from "#components/fragments";
import { CollapsibleSection } from "#components/fragments";
import { useAuthenticatedUserData, useClient } from "#context";

const APIUsageCard: Component = () => {
Expand Down Expand Up @@ -30,13 +30,12 @@ const APIUsageCard: Component = () => {
};

return (
<TitledCard icon={mdiPoll} label="API usage">
<CollapsibleSection icon={mdiPoll} label="API usage">
<Button
size="large"
class="m-0 w-full flex items-start flex-col rounded-xl"
badge
hover={false}
color="contrast"
loading={usage.loading}
>
<span class="text-gray-500 dark:text-gray-400 text-xs font-semibold">Current usage</span>
Expand Down Expand Up @@ -64,7 +63,7 @@ const APIUsageCard: Component = () => {
<b>{numberFormatter.format(subscription()?.plan === "team" ? 10000 : 5000)}</b> API requests
per month. Additional requests are billed at <b>$0.001</b> per request.
</p>
</TitledCard>
</CollapsibleSection>
);
};

Expand Down
8 changes: 4 additions & 4 deletions apps/web/src/ee/settings/billing/change-plan-card.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { PriceTag } from "./price-tag";
import { mdiCog } from "@mdi/js";
import { Button } from "@vrite/components";
import { Component, Match, Show, Switch, createMemo, createResource } from "solid-js";
import { TitledCard } from "#components/fragments";
import { Button } from "#components/primitives";
import { CollapsibleSection } from "#components/fragments";
import { useAuthenticatedUserData, useClient, useConfirmationModal } from "#context";
import { navigateAndReload } from "#lib/utils";

Expand Down Expand Up @@ -46,7 +46,7 @@ const ChangePlanCard: Component = () => {
};

return (
<TitledCard icon={mdiCog} label="Change plan">
<CollapsibleSection icon={mdiCog} label="Change plan">
<Button
size="large"
class="m-0 w-full flex items-start flex-col rounded-xl"
Expand Down Expand Up @@ -91,7 +91,7 @@ const ChangePlanCard: Component = () => {
</Match>
</Switch>
</Show>
</TitledCard>
</CollapsibleSection>
);
};

Expand Down
16 changes: 8 additions & 8 deletions apps/web/src/ee/settings/billing/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { ChangePlanCard } from "./change-plan-card";
import { PriceTag } from "./price-tag";
import { Match, Show, Switch, createMemo, createSignal } from "solid-js";
import { mdiCreditCardEdit, mdiInformation } from "@mdi/js";
import { Button, IconButton, Tooltip } from "@vrite/components";
import dayjs from "dayjs";
import { Button, IconButton, Tooltip } from "#components/primitives";
import { SettingsSectionComponent } from "#views/settings/view";
import { TitledCard } from "#components/fragments";
import { CollapsibleSection } from "#components/fragments";
import { hasPermission, useAuthenticatedUserData, useClient } from "#context";

const BillingSection: SettingsSectionComponent = (props) => {
Expand Down Expand Up @@ -57,14 +57,16 @@ const BillingSection: SettingsSectionComponent = (props) => {
});

return (
<div class="flex justify-center flex-col items-start w-full gap-5">
<TitledCard icon={mdiInformation} label={subscription()?.plan ? "Active plan" : "Subscribe"}>
<div class="flex justify-center flex-col items-start w-full">
<CollapsibleSection
icon={mdiInformation}
label={subscription()?.plan ? "Active plan" : "Subscribe"}
>
<Button
size="large"
class="m-0 w-full flex items-center rounded-xl min-h-11 flex-col items-start"
badge={Boolean(subscription()?.plan)}
hover={!subscription()?.plan}
color="contrast"
loading={loadingCheckout() === "team"}
onClick={() => {
if (!subscription()?.plan) checkout("team");
Expand Down Expand Up @@ -94,7 +96,6 @@ const BillingSection: SettingsSectionComponent = (props) => {
class="m-0 w-full flex items-center rounded-xl min-h-11 flex-col items-start"
badge={Boolean(subscription()?.plan)}
hover={!subscription()?.plan}
color="contrast"
loading={loadingCheckout() === "personal"}
onClick={() => {
if (!subscription()?.plan) checkout("personal");
Expand Down Expand Up @@ -132,15 +133,14 @@ const BillingSection: SettingsSectionComponent = (props) => {
<Button
class="inline-flex m-0 px-1 py-0 rounded-md"
text="soft"
color="contrast"
onClick={manageSubscription}
disabled={loadingPortal()}
>
Cancel subscription
</Button>
</div>
</Show>
</TitledCard>
</CollapsibleSection>
<Show when={subscription()?.plan && hasPermission("manageBilling")}>
<APIUsageCard />
<ChangePlanCard />
Expand Down
31 changes: 21 additions & 10 deletions apps/web/src/lib/editor/extensions/image/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Component, Show, createSignal } from "solid-js";
import { nanoid } from "nanoid";
import { debounce } from "@solid-primitives/scheduled";
import clsx from "clsx";
import { uploadFile as uploadFileUtil } from "#lib/utils";
import { createRef, uploadFile as uploadFileUtil } from "#lib/utils";
import { Card, IconButton, Input, Tooltip } from "#components/primitives";

interface ImageMenuProps {
Expand All @@ -16,6 +16,7 @@ const ImageMenu: Component<ImageMenuProps> = (props) => {
const { storage } = props.state.extension;
const [inputMode, setInputMode] = createSignal<"alt" | "src" | "caption">("src");
const [uploading, setUploading] = createSignal(false);
const [inputValue, setInputValue] = createRef("");
const attrs = (): ImageAttributes => props.state.node.attrs;
const options = (): ImageOptions => props.state.extension.options;
const placeholder = (): string => {
Expand Down Expand Up @@ -52,15 +53,14 @@ const ImageMenu: Component<ImageMenuProps> = (props) => {
<div
class={clsx(
"pointer-events-auto flex bg-gray-50 dark:bg-gray-900 border-gray-200 dark:border-gray-700 border-y-2 backdrop-blur-sm relative !md:left-unset",
options().cover && "w-full border-t-0",
!options().cover &&
"md:gap-2 w-screen md:flex-1 md:border-0 md:rounded-2xl !md:bg-transparent"
options().cover ? "w-full border-2 rounded-xl overflow-hidden" : "w-screen",
"md:gap-2 md:flex-1 md:border-0 md:rounded-2xl md:overflow-visible !md:bg-transparent"
)}
>
<Card
class={clsx(
"p-1 flex m-0 border-0 overflow-hidden rounded-none gap-1",
!options().cover && "md:gap-0.5 md:p-0 md:border-2 md:rounded-xl"
"md:gap-0.5 md:p-0 md:border-2 md:rounded-xl"
)}
>
<Tooltip text="Alt" fixed class="mt-1">
Expand Down Expand Up @@ -93,25 +93,36 @@ const ImageMenu: Component<ImageMenuProps> = (props) => {
<Card
class={clsx(
"px-1 py-1 m-0 border-0 flex-1 overflow-hidden rounded-none",
!options().cover && "md:py-0 md:border-2 md:rounded-xl"
"md:py-0 md:border-2 md:rounded-xl"
)}
>
<Input
wrapperClass={clsx("w-full min-w-unset flex-1", !options().cover && "md:max-w-96")}
wrapperClass={clsx("w-full min-w-unset flex-1", "md:max-w-96")}
class="w-full bg-transparent m-0 flex-1 text-lg"
placeholder={placeholder()}
value={attrs()[inputMode()] || ""}
disabled={!props.state.editor.isEditable}
setValue={(value) => {
updateAttribute.clear();
updateAttribute(inputMode(), value);
setInputValue(value);

if (!options().cover) {
updateAttribute.clear();
updateAttribute(inputMode(), value);
}
}}
onFocus={() => {
setInputValue(attrs()[inputMode()] || "");
}}
onBlur={() => {
props.state.updateAttributes({ [inputMode()]: inputValue() || "" });
setInputValue("");
}}
/>
</Card>
<Card
class={clsx(
"p-1 flex m-0 border-0 overflow-hidden rounded-none gap-1",
!options().cover && "md:gap-0.5 md:p-0 md:border-2 md:rounded-xl"
"md:gap-0.5 md:p-0 md:border-2 md:rounded-xl"
)}
>
<Tooltip text="Image URL" fixed class="mt-1">
Expand Down
Loading

0 comments on commit bb8d73a

Please sign in to comment.