feat: add histoire (#2724)
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/2724
This commit is contained in:
commit
a4424e089c
3
.gitignore
vendored
3
.gitignore
vendored
@ -36,3 +36,6 @@ cypress/videos
|
|||||||
|
|
||||||
# Local Netlify folder
|
# Local Netlify folder
|
||||||
.netlify
|
.netlify
|
||||||
|
|
||||||
|
# histoire
|
||||||
|
.histoire
|
1
env.d.ts
vendored
1
env.d.ts
vendored
@ -1,6 +1,7 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
/// <reference types="vite-svg-loader" />
|
/// <reference types="vite-svg-loader" />
|
||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
|
/// <reference types="@histoire/plugin-vue/components" />
|
||||||
|
|
||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly VITE_IS_ONLINE: boolean
|
readonly VITE_IS_ONLINE: boolean
|
||||||
|
34
histoire.config.ts
Normal file
34
histoire.config.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import {defineConfig, defaultColors} from 'histoire'
|
||||||
|
import {HstVue} from '@histoire/plugin-vue'
|
||||||
|
import {HstScreenshot} from '@histoire/plugin-screenshot'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
setupFile: './src/histoire.setup.ts',
|
||||||
|
storyIgnored: [
|
||||||
|
'**/node_modules/**',
|
||||||
|
'**/dist/**',
|
||||||
|
// see https://kolaente.dev/vikunja/frontend/pulls/2724#issuecomment-42012
|
||||||
|
'**/.direnv/**',
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
HstVue(),
|
||||||
|
HstScreenshot({
|
||||||
|
// Options here
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
title: 'Vikunja',
|
||||||
|
colors: {
|
||||||
|
// https://histoire.dev/guide/config.html#builtin-colors
|
||||||
|
gray: defaultColors.zinc,
|
||||||
|
primary: defaultColors.cyan,
|
||||||
|
},
|
||||||
|
// logo: {
|
||||||
|
// square: './img/square.png',
|
||||||
|
// light: './img/light.png',
|
||||||
|
// dark: './img/dark.png',
|
||||||
|
// },
|
||||||
|
// logoHref: 'https://acme.com',
|
||||||
|
// favicon: './favicon.ico',
|
||||||
|
},
|
||||||
|
})
|
@ -19,7 +19,10 @@
|
|||||||
"browserslist:update": "pnpm dlx browserslist@latest --update-db",
|
"browserslist:update": "pnpm dlx browserslist@latest --update-db",
|
||||||
"fonts:update": "pnpm fonts:download && pnpm fonts:subset",
|
"fonts:update": "pnpm fonts:download && pnpm fonts:subset",
|
||||||
"fonts:download": "./scripts/fonts-download.sh",
|
"fonts:download": "./scripts/fonts-download.sh",
|
||||||
"fonts:subset": "./scripts/fonts-subset.sh"
|
"fonts:subset": "./scripts/fonts-subset.sh",
|
||||||
|
"story:dev": "histoire dev",
|
||||||
|
"story:build": "histoire build",
|
||||||
|
"story:preview": "histoire preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "6.2.1",
|
"@fortawesome/fontawesome-svg-core": "6.2.1",
|
||||||
@ -74,6 +77,8 @@
|
|||||||
"@cypress/vite-dev-server": "5.0.2",
|
"@cypress/vite-dev-server": "5.0.2",
|
||||||
"@cypress/vue": "5.0.3",
|
"@cypress/vue": "5.0.3",
|
||||||
"@faker-js/faker": "7.6.0",
|
"@faker-js/faker": "7.6.0",
|
||||||
|
"@histoire/plugin-screenshot": "0.12.4",
|
||||||
|
"@histoire/plugin-vue": "0.12.4",
|
||||||
"@rushstack/eslint-patch": "1.2.0",
|
"@rushstack/eslint-patch": "1.2.0",
|
||||||
"@types/codemirror": "5.60.6",
|
"@types/codemirror": "5.60.6",
|
||||||
"@types/dompurify": "2.4.0",
|
"@types/dompurify": "2.4.0",
|
||||||
@ -99,6 +104,7 @@
|
|||||||
"eslint": "8.31.0",
|
"eslint": "8.31.0",
|
||||||
"eslint-plugin-vue": "9.8.0",
|
"eslint-plugin-vue": "9.8.0",
|
||||||
"happy-dom": "8.1.1",
|
"happy-dom": "8.1.1",
|
||||||
|
"histoire": "0.12.4",
|
||||||
"netlify-cli": "12.5.0",
|
"netlify-cli": "12.5.0",
|
||||||
"postcss": "8.4.20",
|
"postcss": "8.4.20",
|
||||||
"postcss-easing-gradients": "3.0.1",
|
"postcss-easing-gradients": "3.0.1",
|
||||||
|
947
pnpm-lock.yaml
generated
947
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
58
src/components/base/BaseButton.story.vue
Normal file
58
src/components/base/BaseButton.story.vue
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import {logEvent} from 'histoire/client'
|
||||||
|
import {reactive} from 'vue'
|
||||||
|
import {createRouter, createMemoryHistory} from 'vue-router'
|
||||||
|
import BaseButton from './BaseButton.vue'
|
||||||
|
|
||||||
|
function setupApp({ app }) {
|
||||||
|
// Router mock
|
||||||
|
app.use(createRouter({
|
||||||
|
history: createMemoryHistory(),
|
||||||
|
routes: [
|
||||||
|
{ path: '/', name: 'home', component: { render: () => null } },
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
disabled: false,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Story :setup-app="setupApp" :layout="{ type: 'grid', width: '200px' }">
|
||||||
|
<Variant title="custom">
|
||||||
|
<template #controls>
|
||||||
|
<HstCheckbox v-model="state.disabled" title="Disabled" />
|
||||||
|
</template>
|
||||||
|
<BaseButton :disabled="state.disabled">
|
||||||
|
Hello!
|
||||||
|
</BaseButton>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="disabled">
|
||||||
|
<BaseButton disabled>
|
||||||
|
Hello!
|
||||||
|
</BaseButton>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="router link">
|
||||||
|
<BaseButton :to="'home'">
|
||||||
|
Hello!
|
||||||
|
</BaseButton>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="external link">
|
||||||
|
<BaseButton href="https://vikunja.io">
|
||||||
|
Hello!
|
||||||
|
</BaseButton>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="button">
|
||||||
|
<BaseButton @click="logEvent('Click', $event)">
|
||||||
|
Hello!
|
||||||
|
</BaseButton>
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
@ -61,12 +61,12 @@ export type BaseButtonTypes = typeof BASE_BUTTON_TYPES_MAP[keyof typeof BASE_BUT
|
|||||||
|
|
||||||
import {unrefElement} from '@vueuse/core'
|
import {unrefElement} from '@vueuse/core'
|
||||||
import {ref, type HTMLAttributes} from 'vue'
|
import {ref, type HTMLAttributes} from 'vue'
|
||||||
import type {RouteLocationNamedRaw} from 'vue-router'
|
import type {RouteLocationRaw} from 'vue-router'
|
||||||
|
|
||||||
export interface BaseButtonProps extends HTMLAttributes {
|
export interface BaseButtonProps extends HTMLAttributes {
|
||||||
type?: BaseButtonTypes
|
type?: BaseButtonTypes
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
to?: RouteLocationNamedRaw
|
to?: RouteLocationRaw
|
||||||
href?: string
|
href?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
src/components/input/Button.story.vue
Normal file
26
src/components/input/Button.story.vue
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import {logEvent} from 'histoire/client'
|
||||||
|
import XButton from './button.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Story :layout="{ type: 'grid', width: '200px' }">
|
||||||
|
<Variant title="primary">
|
||||||
|
<XButton @click="logEvent('Click', $event)" variant="primary">
|
||||||
|
Order pizza!
|
||||||
|
</XButton>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="secondary">
|
||||||
|
<XButton @click="logEvent('Click', $event)" variant="secondary">
|
||||||
|
Order spaghetti!
|
||||||
|
</XButton>
|
||||||
|
</Variant>
|
||||||
|
|
||||||
|
<Variant title="tertiary">
|
||||||
|
<XButton @click="logEvent('Click', $event)" variant="tertiary">
|
||||||
|
Order tortellini!
|
||||||
|
</XButton>
|
||||||
|
</Variant>
|
||||||
|
</Story>
|
||||||
|
</template>
|
14
src/components/input/ColorPicker.story.vue
Normal file
14
src/components/input/ColorPicker.story.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import {reactive} from 'vue'
|
||||||
|
import ColorPicker from './ColorPicker.vue'
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
color: '#f2f2f2',
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Story :layout="{ type: 'grid', width: '200px' }">
|
||||||
|
<ColorPicker v-model="state.color" />
|
||||||
|
</Story>
|
||||||
|
</template>
|
@ -37,6 +37,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, ref, toRef, watch} from 'vue'
|
import {computed, ref, toRef, watch} from 'vue'
|
||||||
import {createRandomID} from '@/helpers/randomId'
|
import {createRandomID} from '@/helpers/randomId'
|
||||||
|
import XButton from '@/components/input/button.vue'
|
||||||
|
|
||||||
const DEFAULT_COLORS = [
|
const DEFAULT_COLORS = [
|
||||||
'#1973ff',
|
'#1973ff',
|
11
src/components/misc/Card.story.vue
Normal file
11
src/components/misc/Card.story.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import Card from './card.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Story :layout="{ type: 'grid', width: '200px' }">
|
||||||
|
<Card>
|
||||||
|
Card content
|
||||||
|
</Card>
|
||||||
|
</Story>
|
||||||
|
</template>
|
25
src/histoire.setup.ts
Normal file
25
src/histoire.setup.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { defineSetupVue3 } from '@histoire/plugin-vue'
|
||||||
|
import {i18n} from './i18n'
|
||||||
|
|
||||||
|
// import './histoire.css' // Import global CSS
|
||||||
|
import './styles/global.scss'
|
||||||
|
|
||||||
|
import {createPinia} from 'pinia'
|
||||||
|
|
||||||
|
import FontAwesomeIcon from '@/components/misc/Icon'
|
||||||
|
import XButton from '@/components/input/button.vue'
|
||||||
|
import Modal from '@/components/misc/modal.vue'
|
||||||
|
import Card from '@/components/misc/card.vue'
|
||||||
|
|
||||||
|
|
||||||
|
export const setupVue3 = defineSetupVue3(({ app }) => {
|
||||||
|
// Add Pinia store
|
||||||
|
const pinia = createPinia()
|
||||||
|
app.use(pinia)
|
||||||
|
app.use(i18n)
|
||||||
|
|
||||||
|
app.component('icon', FontAwesomeIcon)
|
||||||
|
app.component('XButton', XButton)
|
||||||
|
app.component('modal', Modal)
|
||||||
|
app.component('card', Card)
|
||||||
|
})
|
@ -115,7 +115,7 @@ import {useI18n} from 'vue-i18n'
|
|||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import Editor from '@/components/input/AsyncEditor'
|
import Editor from '@/components/input/AsyncEditor'
|
||||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
import ColorPicker from '@/components/input/ColorPicker.vue'
|
||||||
|
|
||||||
import LabelModel from '@/models/label'
|
import LabelModel from '@/models/label'
|
||||||
import type {ILabel} from '@/modelTypes/ILabel'
|
import type {ILabel} from '@/modelTypes/ILabel'
|
||||||
|
@ -40,7 +40,7 @@ import {useI18n} from 'vue-i18n'
|
|||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
import CreateEdit from '@/components/misc/create-edit.vue'
|
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
import ColorPicker from '@/components/input/ColorPicker.vue'
|
||||||
|
|
||||||
import LabelModel from '@/models/label'
|
import LabelModel from '@/models/label'
|
||||||
import {useLabelStore} from '@/stores/labels'
|
import {useLabelStore} from '@/stores/labels'
|
||||||
|
@ -39,7 +39,7 @@ import {useRouter, useRoute} from 'vue-router'
|
|||||||
import ListService from '@/services/list'
|
import ListService from '@/services/list'
|
||||||
import ListModel from '@/models/list'
|
import ListModel from '@/models/list'
|
||||||
import CreateEdit from '@/components/misc/create-edit.vue'
|
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
import ColorPicker from '@/components/input/ColorPicker.vue'
|
||||||
|
|
||||||
import {success} from '@/message'
|
import {success} from '@/message'
|
||||||
import {useTitle} from '@/composables/useTitle'
|
import {useTitle} from '@/composables/useTitle'
|
||||||
|
@ -75,7 +75,7 @@ import {useRouter} from 'vue-router'
|
|||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import Editor from '@/components/input/AsyncEditor'
|
import Editor from '@/components/input/AsyncEditor'
|
||||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
import ColorPicker from '@/components/input/ColorPicker.vue'
|
||||||
import CreateEdit from '@/components/misc/create-edit.vue'
|
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||||
|
|
||||||
import type {IList} from '@/modelTypes/IList'
|
import type {IList} from '@/modelTypes/IList'
|
||||||
|
@ -50,7 +50,7 @@ import {useRouter} from 'vue-router'
|
|||||||
|
|
||||||
import Message from '@/components/misc/message.vue'
|
import Message from '@/components/misc/message.vue'
|
||||||
import CreateEdit from '@/components/misc/create-edit.vue'
|
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
import ColorPicker from '@/components/input/ColorPicker.vue'
|
||||||
|
|
||||||
import NamespaceModel from '@/models/namespace'
|
import NamespaceModel from '@/models/namespace'
|
||||||
import NamespaceService from '@/services/namespace'
|
import NamespaceService from '@/services/namespace'
|
||||||
|
@ -62,7 +62,7 @@ import router from '@/router'
|
|||||||
|
|
||||||
import AsyncEditor from '@/components/input/AsyncEditor'
|
import AsyncEditor from '@/components/input/AsyncEditor'
|
||||||
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
|
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
|
||||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
import ColorPicker from '@/components/input/ColorPicker.vue'
|
||||||
import CreateEdit from '@/components/misc/create-edit.vue'
|
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||||
|
|
||||||
import NamespaceService from '@/services/namespace'
|
import NamespaceService from '@/services/namespace'
|
||||||
|
@ -465,7 +465,7 @@ import BaseButton from '@/components/base/BaseButton.vue'
|
|||||||
// partials
|
// partials
|
||||||
import Attachments from '@/components/tasks/partials/attachments.vue'
|
import Attachments from '@/components/tasks/partials/attachments.vue'
|
||||||
import ChecklistSummary from '@/components/tasks/partials/checklist-summary.vue'
|
import ChecklistSummary from '@/components/tasks/partials/checklist-summary.vue'
|
||||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
import ColorPicker from '@/components/input/ColorPicker.vue'
|
||||||
import Comments from '@/components/tasks/partials/comments.vue'
|
import Comments from '@/components/tasks/partials/comments.vue'
|
||||||
import CreatedUpdated from '@/components/tasks/partials/createdUpdated.vue'
|
import CreatedUpdated from '@/components/tasks/partials/createdUpdated.vue'
|
||||||
import Datepicker from '@/components/input/datepicker.vue'
|
import Datepicker from '@/components/input/datepicker.vue'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user