diff --git a/pkgs/clan-app/ui/src/components/v2/Divider/Divider.css b/pkgs/clan-app/ui/src/components/v2/Divider/Divider.css index ee1f04f0c..322c13035 100644 --- a/pkgs/clan-app/ui/src/components/v2/Divider/Divider.css +++ b/pkgs/clan-app/ui/src/components/v2/Divider/Divider.css @@ -1,15 +1,15 @@ -div.divider { - @apply bg-inv-2; +hr { + @apply border-none outline-none bg-inv-2; &.inverted { @apply bg-def-3; } - &.horizontal { + &[data-orientation="horizontal"] { @apply w-full h-px; } - &.vertical { + &[data-orientation="vertical"] { @apply h-full w-px; } } diff --git a/pkgs/clan-app/ui/src/components/v2/Divider/Divider.tsx b/pkgs/clan-app/ui/src/components/v2/Divider/Divider.tsx index 08ef35734..f6eb728e2 100644 --- a/pkgs/clan-app/ui/src/components/v2/Divider/Divider.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Divider/Divider.tsx @@ -1,14 +1,18 @@ import "./Divider.css"; import cx from "classnames"; +import { Separator, SeparatorRootProps } from "@kobalte/core/separator"; -export interface DividerProps { +export interface DividerProps extends Pick { inverted?: boolean; - orientation?: "horizontal" | "vertical"; } export const Divider = (props: DividerProps) => { const inverted = props.inverted || false; - const orientation = () => props.orientation || "horizontal"; - return
; + return ( + + ); }; diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.css b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.css index 40ef30eeb..c7ea91258 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.css +++ b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.css @@ -16,6 +16,10 @@ div.form-field { &[data-invalid] { @apply border-semantic-error-4; } + + &[data-readonly] { + @apply cursor-default bg-inherit border-none; + } } } @@ -32,6 +36,10 @@ div.form-field { &[data-disabled] { @apply bg-def-4 border-none; } + + &[data-readonly] { + @apply bg-inherit; + } } } } diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.stories.tsx b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.stories.tsx index 9ce48ab7a..ed53e4eba 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.stories.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.stories.tsx @@ -94,7 +94,15 @@ export const Disabled: Story = { }, }; -export const ReadOnly: Story = { +export const ReadOnlyUnchecked: Story = { + args: { + ...Tooltip.args, + readOnly: true, + defaultChecked: false, + }, +}; + +export const ReadOnlyChecked: Story = { args: { ...Tooltip.args, readOnly: true, diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.tsx b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.tsx index 7a6b753d1..16bf1d889 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.tsx @@ -11,37 +11,64 @@ import { PolymorphicProps } from "@kobalte/core/polymorphic"; import "./Checkbox.css"; import { FieldProps } from "./Field"; import { Orienter } from "./Orienter"; +import { Show } from "solid-js"; export type CheckboxProps = FieldProps & KCheckboxRootProps & { input?: PolymorphicProps<"input", KCheckboxInputProps<"input">>; }; -export const Checkbox = (props: CheckboxProps) => ( - - - - -); +export const Checkbox = (props: CheckboxProps) => { + const alignment = () => + (props.orientation || "vertical") == "vertical" ? "start" : "center"; + + const iconChecked = ( + + ); + + const iconUnchecked = ( + + ); + + return ( + + + + + ); +}; diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Combobox.css b/pkgs/clan-app/ui/src/components/v2/Form/Combobox.css index eeec2f2de..e0c37c22d 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Combobox.css +++ b/pkgs/clan-app/ui/src/components/v2/Form/Combobox.css @@ -1,9 +1,9 @@ div.form-field.combobox { div.control { - @apply flex flex-col w-full gap-2; + @apply flex flex-col size-full gap-2; div.selected-options { - @apply flex flex-wrap gap-1 w-full min-h-5; + @apply flex flex-wrap gap-1 size-full min-h-5; } div.input-container { @@ -44,7 +44,8 @@ div.form-field.combobox { } &[data-readonly] { - @apply outline-def-2 cursor-not-allowed; + @apply outline-none border-none bg-inherit; + @apply p-0 resize-none; } } @@ -76,6 +77,10 @@ div.form-field.combobox { & > input { @apply px-1.5 py-1; font-size: 0.75rem; + + &[data-readonly] { + @apply p-0; + } } & > button.trigger { @@ -111,6 +116,10 @@ div.form-field.combobox { &[data-invalid] { @apply outline-semantic-error-4; } + + &[data-readonly] { + @apply outline-none border-none bg-inherit cursor-auto; + } } } } diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Combobox.stories.tsx b/pkgs/clan-app/ui/src/components/v2/Form/Combobox.stories.tsx index 804de9335..0b3c5b7fc 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Combobox.stories.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Form/Combobox.stories.tsx @@ -124,6 +124,7 @@ export const ReadOnly: Story = { args: { ...Tooltip.args, readOnly: true, + defaultValue: "foo", }, }; diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Combobox.tsx b/pkgs/clan-app/ui/src/components/v2/Form/Combobox.tsx index 8a2a01db3..af3426756 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Combobox.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Form/Combobox.tsx @@ -83,14 +83,18 @@ export const DefaultItemControl = (
-
- - - - - - -
+ {!(props.readOnly && props.multiple) && ( +
+ + {!props.readOnly && ( + + + + + + )} +
+ )} ); @@ -101,7 +105,13 @@ export const Combobox = ( const itemControl = () => props.itemControl || DefaultItemControl; const itemComponent = () => props.itemComponent || DefaultItemComponent; - const align = () => (props.orientation === "horizontal" ? "start" : "center"); + const align = () => { + if (props.readOnly) { + return "center"; + } else { + return props.orientation === "horizontal" ? "start" : "center"; + } + }; return ( label[data-required] { + & > label[data-required] & not(label[data-readonly]) { span.typography::after { @apply fg-def-4 ml-1; diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Label.tsx b/pkgs/clan-app/ui/src/components/v2/Form/Label.tsx index e64fd363d..e0ab91de7 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Label.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Form/Label.tsx @@ -28,6 +28,7 @@ export interface LabelProps { tooltip?: string; icon?: string; inverted?: boolean; + readOnly?: boolean; validationState?: "valid" | "invalid"; } @@ -42,7 +43,7 @@ export const Label = (props: LabelProps) => { hierarchy="label" size={props.size || "default"} color={props.validationState == "invalid" ? "error" : "primary"} - weight="bold" + weight={props.readOnly ? "normal" : "bold"} inverted={props.inverted} > {props.label} diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Orienter.css b/pkgs/clan-app/ui/src/components/v2/Form/Orienter.css index 591afb90e..aea0d4aaa 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Orienter.css +++ b/pkgs/clan-app/ui/src/components/v2/Form/Orienter.css @@ -5,7 +5,7 @@ div.orienter { } &.horizontal { - @apply flex-row gap-2 justify-between; + @apply flex-row justify-start; & > div.form-label { @apply w-1/2 shrink; diff --git a/pkgs/clan-app/ui/src/components/v2/Form/TextInput.css b/pkgs/clan-app/ui/src/components/v2/Form/TextInput.css index ad1ac916a..eceb5fe61 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/TextInput.css +++ b/pkgs/clan-app/ui/src/components/v2/Form/TextInput.css @@ -34,7 +34,13 @@ div.form-field { } &[data-readonly] { - @apply outline-def-2 cursor-not-allowed; + @apply outline-none border-none bg-inherit p-0 cursor-auto resize-none; + } + } + + &.textarea textarea { + &[data-readonly] { + @apply overflow-y-hidden; } } @@ -72,6 +78,10 @@ div.form-field { &.textarea textarea { @apply px-1.5 py-1; font-size: 0.75rem; + + &[data-readonly] { + @apply p-0; + } } &.text div.input-container { @@ -114,6 +124,11 @@ div.form-field { &[data-invalid] { @apply outline-semantic-error-4; } + + &[data-readonly] { + @apply outline-def-2 cursor-auto; + @apply outline-none border-none bg-inherit; + } } } diff --git a/pkgs/clan-app/ui/src/components/v2/Form/TextInput.tsx b/pkgs/clan-app/ui/src/components/v2/Form/TextInput.tsx index 79e21a1ae..fa403f3e7 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/TextInput.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Form/TextInput.tsx @@ -33,7 +33,7 @@ export const TextInput = (props: TextInputProps) => ( {...props} />
- {props.icon && ( + {props.icon && !props.readOnly && ( ( )}
diff --git a/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarNavHeader.css b/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarNavHeader.css index f7aebe092..f33f306df 100644 --- a/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarNavHeader.css +++ b/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarNavHeader.css @@ -4,8 +4,8 @@ div.sidebar-header { background: linear-gradient( 90deg, - theme(colors.bg.inv.3) 0%, - theme(colors.bg.inv.4) 0% + theme(colors.bg.inv.2) 0%, + theme(colors.bg.inv.3) 0% ); & > .dropdown-trigger { diff --git a/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarPane.css b/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarPane.css new file mode 100644 index 000000000..649366633 --- /dev/null +++ b/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarPane.css @@ -0,0 +1,33 @@ +div.sidebar-pane { + @apply h-full w-auto max-w-60 border-none; + + & > div.header { + @apply flex items-center justify-between px-3 py-2 rounded-t-[0.5rem]; + @apply border-t-[1px] border-t-bg-inv-3 + border-r-[1px] border-r-bg-inv-3 + border-b-2 border-b-bg-inv-4 + border-l-[1px] border-l-bg-inv-3; + background: linear-gradient( + 90deg, + theme(colors.bg.inv.3) 0%, + theme(colors.bg.inv.4) 100% + ); + } + + & > div.body { + @apply flex flex-col gap-4 px-2 pt-4 pb-3 w-full h-full; + @apply backdrop-blur-md; + @apply rounded-b-[0.5rem] + border-r-[1px] border-r-bg-inv-3 + border-b-2 border-b-bg-inv-4 + border-l-[1px] border-l-bg-inv-3; + + background: + linear-gradient(0deg, rgba(0, 0, 0, 0.2) 0%, rgba(0, 0, 0, 0.2) 100%), + linear-gradient( + 180deg, + theme(colors.bg.inv.2) 0%, + theme(colors.bg.inv.3) 100% + ); + } +} diff --git a/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarPane.stories.tsx b/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarPane.stories.tsx new file mode 100644 index 000000000..2ef9cc024 --- /dev/null +++ b/pkgs/clan-app/ui/src/components/v2/Sidebar/SidebarPane.stories.tsx @@ -0,0 +1,115 @@ +import type { Meta, StoryObj } from "@kachurun/storybook-solid"; +import { + SidebarPane, + SidebarPaneProps, +} from "@/src/components/v2/Sidebar/SidebarPane"; +import { SidebarSection } from "./SidebarSection"; +import { Divider } from "@/src/components/v2/Divider/Divider"; +import { TextInput } from "@/src/components/v2/Form/TextInput"; +import { TextArea } from "@/src/components/v2/Form/TextArea"; +import { Checkbox } from "@/src/components/v2/Form/Checkbox"; +import { Combobox } from "../Form/Combobox"; + +const meta: Meta = { + title: "Components/Sidebar/Pane", + component: SidebarPane, +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + title: "Neptune", + onClose: () => { + console.log("closing"); + }, + children: ( + <> + { + console.log("saving general"); + }} + > + {(editing) => ( +
+ + + + +