From bd61111ffb7eff8a550f910308bf20b7dd6393dd Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Tue, 18 Jun 2024 11:42:09 +0200 Subject: [PATCH 01/12] add global styles --- .storybook/preview.ts | 13 ++--- src/styles/style.css | 113 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 src/styles/style.css diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 40280b516..116540d01 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,5 +1,5 @@ import type { Preview } from '@storybook/vue3' -import { setup } from "@storybook/vue3" +import { setup } from '@storybook/vue3' import { initialize, mswLoader } from 'msw-storybook-addon' import globalComponents from '../src/plugins/globalComponents' import { newI18n } from '../src/plugins/i18n' @@ -8,6 +8,7 @@ import { handlers as mswHandlers } from './mswHandlers' import 'dripicons/webfont/webfont.css' import 'impresso-theme/dist/css/bootpresso.css' +import '../src/styles/style.css' import '../src/assets/legacy/bootstrap-vue.css' /* @@ -21,13 +22,13 @@ const worker = initialize({ if (pathname.startsWith('/api/')) { throw new Error(`Please add a request handler for ${method} ${pathname}`) } - }, + } }) // it won't load the handlers without this call. May be a bug worker.use(...[]) -setup(app => { +setup((app) => { app.use(pinia) app.use(newI18n()) app.use(globalComponents) @@ -42,10 +43,10 @@ const preview: Preview = { } }, msw: { - handlers: mswHandlers, - }, + handlers: mswHandlers + } }, - loaders: [mswLoader], + loaders: [mswLoader] } export default preview diff --git a/src/styles/style.css b/src/styles/style.css new file mode 100644 index 000000000..5ab64c23f --- /dev/null +++ b/src/styles/style.css @@ -0,0 +1,113 @@ +@font-face { + font-family: 'Satoshi-Variable'; + src: + url('/assets/fonts/Satoshi-Variable.woff2') format('woff2'), + url('/assets/fonts/Satoshi-Variable.woff') format('woff'), + url('/assets/fonts/Satoshi-Variable.ttf') format('truetype'); + font-weight: 300 900; + font-display: swap; + font-style: normal; +} + +@font-face { + font-family: 'Satoshi-VariableItalic'; + src: + url('/assets/fonts/Satoshi-VariableItalic.woff2') format('woff2'), + url('/assets/fonts/Satoshi-VariableItalic.woff') format('woff'), + url('/assets/fonts/Satoshi-VariableItalic.ttf') format('truetype'); + font-weight: 300 900; + font-display: swap; + font-style: italic; +} + +:root { + --impresso-color-paper: #fafbf2; + + --impresso-color-yellow-code: 255, 235, 120; + --impresso-color-yellow: #ffeb78; + --impresso-color-yellow-alpha-20: rgba(255, 235, 120, 0.2); + --impresso-color-yellow-alpha-30: rgba(255, 235, 120, 0.3); + --impresso-color-yellow-alpha-50: rgba(255, 235, 120, 0.5); + --impresso-color-yellow-alpha-80: rgba(255, 235, 120, 0.8); + + --impresso-color-black: #343a40; + --impresso-color-black-rgb: 52, 58, 64; + + --impresso-color-pastel-blue: rgba(86, 204, 242); + --impresso-color-pastel-blue-alpha-20: rgba(86, 204, 242, 0.2); + + --impresso-border-radius-xs: 5px; + --impresso-border-radius-sm: 10px; + --impresso-border-radius-md: 15px; + --impresso-border-radius-lg: 20px; + --impresso-border-radius-xl: 30px; + --impresso-font-size-smallcaps: 0.72em; + --impresso-letter-spacing-smallcaps: 0.08em; + --impresso-font-size-smaller: 0.85em; + --impresso-wght: 450; + --impresso-wght-bold: 700; + --impresso-wght-smallcaps: 580; + --impresso-wght-smallcaps-bold: 800; + --clr-white: #f8f8ff; + --clr-white-rgba-20: #ffffff33; + --clr-dark: var(--impresso-color-black); + + --clr-grey-100: #3d4146; + --clr-grey-200: #5b5e65; + --clr-grey-300: #84868e; + --clr-grey-400: #a9aab4; + --clr-grey-500: #c2c3cb; + --clr-grey-600: #d4d5e1; + --clr-grey-700: #e1e1ee; + --clr-grey-800: #ececfb; + --clr-grey-900: #f8f8ff; + --clr-grey-100-rgba-20: #464d5333; + --clr-grey-200-rgba-20: #585d6633; + --clr-grey-300-rgba-20: #7c7f8c33; + --clr-grey-400-rgba-20: #a0a1a333; + --clr-grey-500-rgba-20: #b1b2c633; + --clr-grey-600-rgba-20: #c3c4d933; + --clr-grey-700-rgba-20: #d5d5ec33; + --clr-grey-800-rgba-20: #e7e7ff33; + --clr-grey-900-rgba-20: #f8f8ff33; + + --spacing-1: 0.25rem; + --spacing-2: 0.5rem; + --spacing-3: 1rem; + --spacing-4: 1.5rem; + --spacing-5: 3rem; + --negative-spacing-1: -0.25rem; + --negative-spacing-2: -0.5rem; + --negative-spacing-3: -1rem; + --negative-spacing-4: -1.5rem; + --negative-spacing-5: -3rem; + + --accent: #28a745; + --impresso-yellow: #ffeb78; + --border-radius-sm: 3px; + --border-radius-md: 8px; + --border-radius-lg: 12px; + + /* Bootstrap overrides */ + --bs-font-sans-serif: 'Satoshi-Variable', sans-serif; + --bs-font-sans-serif-italic: 'Satoshi-VariableItalic', sans-serif; + --bs-font-serif-italic: 'questa', serif; + --bs-font-serif: 'questa', serif; + --bs-border-radius-lg: var(--impresso-border-radius-lg); + --bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.125); + --bs-box-shadow-md: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + --bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175); + --bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075); + + --bs-font-size-base: 1rem; + --impresso-font-size-3: 1.75rem; + --impresso-font-size-4: 1.5rem; +} + +body { + font-family: var(--bs-font-sans-serif); + font-weight: 450; + font-variation-settings: 'wght' 450; + text-rendering: optimizeLegibility; +} From 753b74d654a4bae473aaecc39c092742b01c15b4 Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Tue, 18 Jun 2024 11:42:33 +0200 Subject: [PATCH 02/12] add TutorialMonitor component and its story --- src/components/TutorialMonitor.vue | 14 ++++++++++++ .../stories/TutorialMonitor.stories.ts | 22 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/components/TutorialMonitor.vue create mode 100644 src/components/stories/TutorialMonitor.stories.ts diff --git a/src/components/TutorialMonitor.vue b/src/components/TutorialMonitor.vue new file mode 100644 index 000000000..4f341cab3 --- /dev/null +++ b/src/components/TutorialMonitor.vue @@ -0,0 +1,14 @@ + + diff --git a/src/components/stories/TutorialMonitor.stories.ts b/src/components/stories/TutorialMonitor.stories.ts new file mode 100644 index 000000000..c4a2ddb16 --- /dev/null +++ b/src/components/stories/TutorialMonitor.stories.ts @@ -0,0 +1,22 @@ +import type { Meta, StoryObj } from '@storybook/vue3' +import TutorialMonitor from '@/components/TutorialMonitor.vue' + +const meta: Meta = { + title: 'Components/TutorialMonitor', + component: TutorialMonitor, + tags: ['autodocs'], + + args: { + title: 'Tutorial Monitor' + } +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + title: 'Tutorial Monitor' + } +} From 56d5fceefa7d1e5df7f40df9a51786a935590b9f Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Tue, 18 Jun 2024 12:24:27 +0200 Subject: [PATCH 03/12] basic chevron and transition to collapse list of tutorials --- src/components/TutorialMonitor.vue | 81 ++++++++++++++++++- src/components/base/Icon.vue | 67 ++++++++------- .../stories/TutorialMonitor.stories.ts | 1 - 3 files changed, 117 insertions(+), 32 deletions(-) diff --git a/src/components/TutorialMonitor.vue b/src/components/TutorialMonitor.vue index 4f341cab3..0f3a609aa 100644 --- a/src/components/TutorialMonitor.vue +++ b/src/components/TutorialMonitor.vue @@ -1,9 +1,33 @@ + diff --git a/src/components/base/Icon.vue b/src/components/base/Icon.vue index 7d73b5bfa..3eeb350d2 100644 --- a/src/components/base/Icon.vue +++ b/src/components/base/Icon.vue @@ -3,7 +3,7 @@ :width="width * scaleValue" :height="height * scaleValue" :viewBox="computedSvgViewbox" - :class="{'Icon': true }" + :class="{ Icon: true }" > = { height: 1792, paths: [ { - d: - 'M1519 776q62 0 103.5 40.5t41.5 101.5q0 97-93 130l-172 59 56 167q7 21 7 47 0 59-42 102t-101 43q-47 0-85.5-27t-53.5-72l-55-165-310 106 55 164q8 24 8 47 0 59-42 102t-102 43q-47 0-85-27t-53-72l-55-163-153 53q-29 9-50 9-61 0-101.5-40t-40.5-101q0-47 27.5-85t71.5-53l156-53-105-313-156 54q-26 8-48 8-60 0-101-40.5t-41-100.5q0-47 27.5-85t71.5-53l157-53-53-159q-8-24-8-47 0-60 42-102.5t102-42.5q47 0 85 27t53 72l54 160 310-105-54-160q-8-24-8-47 0-59 42.5-102t101.5-43q47 0 85.5 27.5t53.5 71.5l53 161 162-55q21-6 43-6 60 0 102.5 39.5t42.5 98.5q0 45-30 81.5t-74 51.5l-157 54 105 316 164-56q24-8 46-8zM725 1038l310-105-105-315-310 107z', - }, - ], + d: 'M1519 776q62 0 103.5 40.5t41.5 101.5q0 97-93 130l-172 59 56 167q7 21 7 47 0 59-42 102t-101 43q-47 0-85.5-27t-53.5-72l-55-165-310 106 55 164q8 24 8 47 0 59-42 102t-102 43q-47 0-85-27t-53-72l-55-163-153 53q-29 9-50 9-61 0-101.5-40t-40.5-101q0-47 27.5-85t71.5-53l156-53-105-313-156 54q-26 8-48 8-60 0-101-40.5t-41-100.5q0-47 27.5-85t71.5-53l157-53-53-159q-8-24-8-47 0-60 42-102.5t102-42.5q47 0 85 27t53 72l54 160 310-105-54-160q-8-24-8-47 0-59 42.5-102t101.5-43q47 0 85.5 27.5t53.5 71.5l53 161 162-55q21-6 43-6 60 0 102.5 39.5t42.5 98.5q0 45-30 81.5t-74 51.5l-157 54 105 316 164-56q24-8 46-8zM725 1038l310-105-105-315-310 107z' + } + ] }, play: { width: 24, @@ -58,10 +57,9 @@ const Icons: Record = { paths: [ { style: 'fill:white; stroke:black; stroke-width:1px;', - d: - 'M6.90588 4.53682C6.50592 4.2998 6 4.58808 6 5.05299V18.947C6 19.4119 6.50592 19.7002 6.90588 19.4632L18.629 12.5162C19.0211 12.2838 19.0211 11.7162 18.629 11.4838L6.90588 4.53682Z', - }, - ], + d: 'M6.90588 4.53682C6.50592 4.2998 6 4.58808 6 5.05299V18.947C6 19.4119 6.50592 19.7002 6.90588 19.4632L18.629 12.5162C19.0211 12.2838 19.0211 11.7162 18.629 11.4838L6.90588 4.53682Z' + } + ] }, edit: { width: 24, @@ -69,14 +67,13 @@ const Icons: Record = { paths: [ { style: 'stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round;', - d: 'M3 21L12 21H21', + d: 'M3 21L12 21H21' }, { style: 'stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round;', - d: - 'M12.2218 5.82839L15.0503 2.99996L20 7.94971L17.1716 10.7781M12.2218 5.82839L6.61522 11.435C6.42769 11.6225 6.32233 11.8769 6.32233 12.1421L6.32233 16.6776L10.8579 16.6776C11.1231 16.6776 11.3774 16.5723 11.565 16.3847L17.1716 10.7781M12.2218 5.82839L17.1716 10.7781', - }, - ], + d: 'M12.2218 5.82839L15.0503 2.99996L20 7.94971L17.1716 10.7781M12.2218 5.82839L6.61522 11.435C6.42769 11.6225 6.32233 11.8769 6.32233 12.1421L6.32233 16.6776L10.8579 16.6776C11.1231 16.6776 11.3774 16.5723 11.565 16.3847L17.1716 10.7781M12.2218 5.82839L17.1716 10.7781' + } + ] }, check: { width: 24, @@ -84,50 +81,62 @@ const Icons: Record = { paths: [ { style: 'stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round;', - d: 'M7 12.5L10 15.5L17 8.5', + d: 'M7 12.5L10 15.5L17 8.5' }, { - d: - 'M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z', - }, - ], + d: 'M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z' + } + ] }, + chevron: { + width: 24, + height: 24, + paths: [ + { + style: 'fill:white; stroke:black; stroke-width:1px;', + + d: 'M6 9L12 15L18 9' + } + ] + } } const props = defineProps({ name: { type: String, - default: 'slack', + default: 'slack' }, scale: { type: [Number, String], - default: 1, + default: 1 }, paths: { type: Array, - default: () => [], + default: () => [] }, polygons: { type: Array, - default: () => [], + default: () => [] }, width: { type: Number, - default: 24, + default: 24 }, height: { type: Number, - default: 24, + default: 24 }, strokeWidth: { type: Number, - default: 1, - }, + default: 1 + } }) -const computedPaths = computed(() => (props.paths.length ? props.paths as any as Path[] : Icons[props.name].paths)) +const computedPaths = computed(() => + props.paths.length ? (props.paths as any as Path[]) : Icons[props.name].paths +) const computedPolygons = computed(() => - props.polygons.length ? props.polygons as Polygon[] : Icons[props.name].polygons, + props.polygons.length ? (props.polygons as Polygon[]) : Icons[props.name].polygons ) const computedSvgViewbox = computed(() => { const { width, height } = Icons[props.name] diff --git a/src/components/stories/TutorialMonitor.stories.ts b/src/components/stories/TutorialMonitor.stories.ts index c4a2ddb16..4ff52233e 100644 --- a/src/components/stories/TutorialMonitor.stories.ts +++ b/src/components/stories/TutorialMonitor.stories.ts @@ -5,7 +5,6 @@ const meta: Meta = { title: 'Components/TutorialMonitor', component: TutorialMonitor, tags: ['autodocs'], - args: { title: 'Tutorial Monitor' } From 95ea2e500f1fb8a7499e549275b8cd2eb8b5b561 Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Tue, 18 Jun 2024 16:25:14 +0200 Subject: [PATCH 04/12] add offsetHeight to expand the parent component --- src/components/CollapsiblePanel.vue | 154 ++++++++++++++++++ src/components/TutorialMonitor.vue | 125 +++++++------- src/components/TutorialTask.vue | 20 +++ .../stories/TutorialMonitor.stories.ts | 25 ++- src/models/TutorialTask.js | 32 ++++ 5 files changed, 281 insertions(+), 75 deletions(-) create mode 100644 src/components/CollapsiblePanel.vue create mode 100644 src/components/TutorialTask.vue create mode 100644 src/models/TutorialTask.js diff --git a/src/components/CollapsiblePanel.vue b/src/components/CollapsiblePanel.vue new file mode 100644 index 000000000..efcd50c6b --- /dev/null +++ b/src/components/CollapsiblePanel.vue @@ -0,0 +1,154 @@ + + + diff --git a/src/components/TutorialMonitor.vue b/src/components/TutorialMonitor.vue index 0f3a609aa..6df1d662d 100644 --- a/src/components/TutorialMonitor.vue +++ b/src/components/TutorialMonitor.vue @@ -1,91 +1,76 @@ diff --git a/src/components/TutorialTask.vue b/src/components/TutorialTask.vue new file mode 100644 index 000000000..cab8247c5 --- /dev/null +++ b/src/components/TutorialTask.vue @@ -0,0 +1,20 @@ + + diff --git a/src/components/stories/TutorialMonitor.stories.ts b/src/components/stories/TutorialMonitor.stories.ts index 4ff52233e..0fdf1564d 100644 --- a/src/components/stories/TutorialMonitor.stories.ts +++ b/src/components/stories/TutorialMonitor.stories.ts @@ -4,10 +4,7 @@ import TutorialMonitor from '@/components/TutorialMonitor.vue' const meta: Meta = { title: 'Components/TutorialMonitor', component: TutorialMonitor, - tags: ['autodocs'], - args: { - title: 'Tutorial Monitor' - } + tags: ['autodocs'] } export default meta @@ -16,6 +13,24 @@ type Story = StoryObj export const Default: Story = { args: { - title: 'Tutorial Monitor' + title: 'Tutorial Monitor Story', + isCollapsed: false, + tasks: [ + { + id: 'task-1', + title: 'Task 1', + description: 'Description for task 1' + }, + { + id: 'task-2', + title: 'Task 2', + description: 'Description for task 2' + }, + { + id: 'task-3', + title: 'Task 3', + description: 'Description for task 3' + } + ] } } diff --git a/src/models/TutorialTask.js b/src/models/TutorialTask.js new file mode 100644 index 000000000..5524a60b8 --- /dev/null +++ b/src/models/TutorialTask.js @@ -0,0 +1,32 @@ + +export default class TutorialTask { + constructor({ + id = '', + title = '', + description = '', + status = '', + creationDate = null, + completionDate = null + coverUrl = '', + videoUrl = '', + } = {}) { + this.id = String(id); + this.title = String(title); + this.description = String(description); + this.status = String(status); + this.coverUrl = String(coverUrl); + this.videoUrl = String(videoUrl); + + if (creationDate instanceof Date) { + this.creationDate = creationDate; + } else if(creationDate) { + this.creationDate = new Date(creationDate); + } + + if (completionDate instanceof Date) { + this.completionDate = completionDate; + } else if(completionDate) { + this.completionDate = new Date(completionDate); + } + } +} \ No newline at end of file From 449b71d9ede8d0777e326465dc6571916e21e36b Mon Sep 17 00:00:00 2001 From: Daniele Guido Date: Wed, 19 Jun 2024 10:02:53 +0200 Subject: [PATCH 05/12] update style --- src/components/CollapsiblePanel.vue | 15 +++++++++++--- src/components/TutorialMonitor.vue | 27 +++++++++++++++++++------ src/components/TutorialTask.vue | 28 ++++++++++++++++++++++++++ src/components/base/Icon.vue | 2 +- src/styles/style.css | 31 +++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 10 deletions(-) diff --git a/src/components/CollapsiblePanel.vue b/src/components/CollapsiblePanel.vue index efcd50c6b..5e0a6dae1 100644 --- a/src/components/CollapsiblePanel.vue +++ b/src/components/CollapsiblePanel.vue @@ -1,6 +1,10 @@ -
    -
  1. +
      +
    1. @@ -56,7 +57,7 @@ defineProps({ const onTutorialTaskToggled = (idx: number, payload: CollapsiblePanelData) => { console.debug('[TutorialMonitor] idx', idx, '@onTutorialTaskToggled', payload) - offsetHeights[idx] = payload.value ? 0 : payload.expandedHeight + offsetHeights[idx] = payload.value ? 50 : payload.expandedHeight } diff --git a/src/components/TutorialTask.vue b/src/components/TutorialTask.vue index cab8247c5..4ac3a5ba9 100644 --- a/src/components/TutorialTask.vue +++ b/src/components/TutorialTask.vue @@ -4,6 +4,12 @@ :title="task.title" @toggled="(payload: CollapsiblePanelData) => $emit('toggled', payload)" > +
      @@ -15,6 +21,28 @@ defineProps({ task: { type: Object, required: true + }, + taskNum: { + type: Number, + required: true } }) + diff --git a/src/components/base/Icon.vue b/src/components/base/Icon.vue index 3eeb350d2..4e3c7e11d 100644 --- a/src/components/base/Icon.vue +++ b/src/components/base/Icon.vue @@ -93,7 +93,7 @@ const Icons: Record = { height: 24, paths: [ { - style: 'fill:white; stroke:black; stroke-width:1px;', + style: 'fill:transparent; stroke:black; stroke-width:1px;', d: 'M6 9L12 15L18 9' } diff --git a/src/styles/style.css b/src/styles/style.css index 5ab64c23f..fd290e26b 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -43,6 +43,7 @@ --impresso-border-radius-xl: 30px; --impresso-font-size-smallcaps: 0.72em; --impresso-letter-spacing-smallcaps: 0.08em; + --impresso-letter-spacing-smallcaps-md: 0.12em; --impresso-font-size-smaller: 0.85em; --impresso-wght: 450; --impresso-wght-bold: 700; @@ -98,11 +99,14 @@ --bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.125); --bs-box-shadow-md: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); --bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175); + --bs-box-shadow-focus: 0 0 0 0.2rem #ffeb78; --bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075); --bs-font-size-base: 1rem; --impresso-font-size-3: 1.75rem; --impresso-font-size-4: 1.5rem; + + --impresso-transition-ease: cubic-bezier(0.4, 0, 0.2, 1); } body { @@ -111,3 +115,30 @@ body { font-variation-settings: 'wght' 450; text-rendering: optimizeLegibility; } + +/* impresso-specific pseudo-bootstrap implementation */ +.btn-icon { + display: inline-flex; + align-items: center; + justify-content: center; + margin: var(--spacing-2); + padding: var(--spacing-1); + border-radius: 50%; + border: 1px solid transparent; + transition: background-color 0.5s var(--impresso-transition-ease); +} +.btn-icon > path { + fill: transparent; +} +.btn-icon:hover, +.btn-icon.active { + background-color: var(--impresso-yellow); + border-color: var(--impresso-yellow); +} +.btn-icon:hover, +.btn-icon:focus { + box-shadow: var(--bs-box-shadow-focus); +} +.btn-icon.active:focus { + box-shadow: none; +} From 8380a292f38d7460a5ad9392fb085f31aa1e6d44 Mon Sep 17 00:00:00 2001 From: Roman Kalyakin Date: Wed, 19 Jun 2024 15:19:41 +0200 Subject: [PATCH 06/12] optimised collapsible panels --- src/components/CollapsiblePanel.vue | 132 ++++++------------ src/components/TutorialMonitor.vue | 64 +++++---- ...TutorialTask.vue => TutorialTaskPanel.vue} | 37 +++-- src/models/TutorialTask.js | 32 ----- src/models/TutorialTask.ts | 51 +++++++ 5 files changed, 158 insertions(+), 158 deletions(-) rename src/components/{TutorialTask.vue => TutorialTaskPanel.vue} (59%) delete mode 100644 src/models/TutorialTask.js create mode 100644 src/models/TutorialTask.ts diff --git a/src/components/CollapsiblePanel.vue b/src/components/CollapsiblePanel.vue index 5e0a6dae1..b34cd350c 100644 --- a/src/components/CollapsiblePanel.vue +++ b/src/components/CollapsiblePanel.vue @@ -1,22 +1,16 @@ +