feat: move away from carbon components and TinyMCE (#597)

* feat: remove tinymce & replace org sidebar

* chore: PR Fixes

* chore: move ui font into src dir

* remove files in vite config

* use google font import for loading font

* remove custom font

* more fonts update

* remove font bold

* more removals of font bold

* fix import

* checkpoint

* chore: checkpoint (add course & lms shadcn sidebar)

* minor css improvements and try out font sans

* chore: replace carbon components with shadcn's

* chore: replace carbon components with shadcn _ v3

* chore: ui fixes & storybook update

* feat: UI cleanup

* fix: quick ui fixes

* chore: update pnpm-lock.yaml with new dependencies and versions; fix output.css formatting

* chore: add isloading to button

* feat: add loading state to button stories

* chore: feedback fixes

* fix: feedback fixes

* chore: remove console

* fix: PR comments

* fix: PR comments

---------

Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
Adeyemi Adetunji
2025-11-21 12:18:04 +01:00
committed by GitHub
co-authored by Rotimi Best
parent 2145782385
commit cbf6ae7e63
499 changed files with 19708 additions and 15603 deletions
@@ -1,32 +1,32 @@
<script lang="ts">
import { goto } from '$app/navigation';
import pluralize from 'pluralize';
import TrashIcon from '@lucide/svelte/icons/trash';
import { Dropdown, SkeletonPlaceholder, SkeletonText } from 'carbon-components-svelte';
import ArrowLeftIcon from '@lucide/svelte/icons/arrow-left';
import Vote from '$lib/components/Vote/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import Avatar from '$lib/components/Avatar/index.svelte';
import { IconButton } from '$lib/components/IconButton';
import CircleCheckIcon from '$lib/components/Icons/CircleCheckIcon.svelte';
import { currentOrg, isOrgAdmin } from '$lib/utils/store/org';
import { profile } from '$lib/utils/store/user';
import { supabase } from '$lib/utils/functions/supabase';
import { askCommunityValidation, commentInCommunityValidation } from '$lib/utils/functions/validator';
import { snackbar } from '$lib/components/Snackbar/store';
import TextField from '$lib/components/Form/TextField.svelte';
import DeleteModal from '$lib/components/Org/Community/DeleteModal.svelte';
import TextEditor from '$lib/components/TextEditor/index.svelte';
import { calDateDiff } from '$lib/utils/functions/date';
import { untrack } from 'svelte';
import { fetchCourses } from '$lib/utils/services/courses';
import pluralize from 'pluralize';
import { goto } from '$app/navigation';
import * as Select from '@cio/ui/base/select';
import { Skeleton } from '@cio/ui/base/skeleton';
import TrashIcon from '@lucide/svelte/icons/trash';
import ArrowLeftIcon from '@lucide/svelte/icons/arrow-left';
import type { Course } from '$lib/utils/types';
import { profile } from '$lib/utils/store/user';
import { t } from '$lib/utils/functions/translations';
import { courses } from '$lib/components/Courses/store';
import type { Course } from '$lib/utils/types';
import { calDateDiff } from '$lib/utils/functions/date';
import { supabase } from '$lib/utils/functions/supabase';
import { snackbar } from '$lib/components/Snackbar/store';
import { fetchCourses } from '$lib/utils/services/courses';
import { currentOrg, isOrgAdmin } from '$lib/utils/store/org';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { askCommunityValidation, commentInCommunityValidation } from '$lib/utils/functions/validator';
let { data } = $props();
const { slug } = data;
import Vote from '$lib/components/Vote/index.svelte';
import { IconButton } from '$lib/components/IconButton';
import Avatar from '$lib/components/Avatar/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import TextEditor from '$lib/components/TextEditor/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import DeleteModal from '$lib/components/Org/Community/DeleteModal.svelte';
import CircleCheckIcon from '$lib/components/Icons/CircleCheckIcon.svelte';
interface Comment {
id: string;
@@ -53,6 +53,9 @@
courseId: string;
}
let { data } = $props();
const { slug } = data;
let question: Question | undefined = $state();
let comment = $state('');
let errors: {
@@ -390,9 +393,9 @@
<section class="mx-auto max-w-3xl md:mx-10 lg:mb-20">
{#if !question}
<div class="mb-3 px-5 py-10">
<SkeletonText style="width: 25%;" />
<SkeletonText style="width: 100%; margin-bottom: 2rem" />
<SkeletonPlaceholder style="width: 100%; height: 20rem;" />
<Skeleton class="h-4 w-[25%]" />
<Skeleton class="mb-2 h-4 w-full" />
<Skeleton class="h-80 w-full" />
</div>
{:else}
<div class="px-5 py-10">
@@ -403,13 +406,22 @@
<div class="my-5 flex items-center justify-between">
{#if isEditMode}
<TextField bind:value={editContent.title} className="w-full mr-2" errorMessage={errors.title} />
<Dropdown
class="h-full w-[25%]"
size="xl"
label="Select Course"
items={fetchedCourses.map((course) => ({ id: course.id, text: course.title }))}
bind:selectedId={editContent.courseId}
/>
<Select.Root type="single" bind:value={editContent.courseId}>
<Select.Trigger class="h-full w-[25%]">
<p>
{editContent.courseId
? fetchedCourses.find((course) => course.id === editContent.courseId)?.title
: 'Select Course'}
</p>
</Select.Trigger>
<Select.Content>
{#each fetchedCourses as course}
{#if course.id}
<Select.Item value={course.id}>{course.title}</Select.Item>
{/if}
{/each}
</Select.Content>
</Select.Root>
{:else}
<div class="flex items-center">
<Vote value={question.votes} upVote={() => upvoteQuestion('question')} disabled={voted.question} />
@@ -461,19 +473,19 @@
{#if isEditMode && editorInstance}
<div class="my-2">
<TextEditor
bind:value={editContent.body}
placeholder="Give an answer"
onChange={(html) => (editContent.body = html)}
content={editContent.body}
onChange={(content) => (editContent.body = content)}
/>
</div>
{:else}
<section class="prose prose-sm sm:prose p-2">
<section class="prose prose-sm p-2 sm:prose">
{@html question.body}
</section>
{/if}
</div>
<div class="my-8 font-bold">
<div class="my-8">
{pluralize($t('community.answers'), question.totalComments, true)}
</div>
@@ -510,7 +522,7 @@
</IconButton>
{/if}
</header>
<article class="prose prose-sm sm:prose p-2">
<article class="prose prose-sm p-2 sm:prose">
{@html comment.comment}
</article>
</div>
@@ -521,7 +533,7 @@
<div>
{#if !editorInstance}
<TextEditor bind:value={comment} placeholder="Give an answer" onChange={(html) => (comment = html)} />
<TextEditor placeholder="Give an answer" content={comment} onChange={(content) => (comment = content)} />
{/if}
<div class="mr-2 flex justify-end">