diff --git a/package.json b/package.json
index ff6357b4601..2f8590b1588 100644
--- a/package.json
+++ b/package.json
@@ -103,7 +103,7 @@
"requirejs": "2.3.6",
"rollup-plugin-node-polyfills": "0.2.1",
"rollup-plugin-visualizer": "5.9.0",
- "sass": "1.62.1",
+ "sass": "1.69.7",
"ts-jest": "29.1.1",
"ts-node": "10.9.2",
"tslib": "2.5.0",
diff --git a/packages/design-system/build/build-tokens.js b/packages/design-system/build/build-tokens.js
index c32f3ccbc3d..50eb767a5b3 100644
--- a/packages/design-system/build/build-tokens.js
+++ b/packages/design-system/build/build-tokens.js
@@ -10,12 +10,27 @@ StyleDictionary.extend({
parsers: [
{
pattern: /\.yaml$/,
- parse: ({ contents }) => yaml.parse(contents)
+ parse: ({ contents, filePath }) => {
+ // This is a bit of a hack to prevent name collisions which would drop the tokens then
+ if (filePath.split('/').some((n) => n === 'docs')) {
+ const parsed = yaml.parse(contents)
+
+ Object.keys(parsed).forEach((k) => {
+ parsed['docs-' + k] = parsed[k]
+
+ delete parsed[k]
+ })
+
+ return parsed
+ }
+
+ return yaml.parse(contents)
+ }
}
],
source: [path.join(__dirname, '../src/tokens/**/*.yaml')],
platforms: {
- default: {
+ ods: {
transforms: ['name/cti/kebab', 'transform/ods/namespace'],
buildPath: 'src/assets/tokens/',
files: [
diff --git a/packages/design-system/build/build-tokens/transform-namespace.js b/packages/design-system/build/build-tokens/transform-namespace.js
index 03f54109245..16439600a5c 100644
--- a/packages/design-system/build/build-tokens/transform-namespace.js
+++ b/packages/design-system/build/build-tokens/transform-namespace.js
@@ -2,8 +2,6 @@ module.exports = {
name: 'transform/ods/namespace',
type: 'name',
transformer: function (prop) {
- return ['oc', prop.filePath.split('/').some((n) => n === 'docs') ? 'docs' : '', prop.name]
- .filter(Boolean)
- .join('-')
+ return ['oc', prop.name].filter(Boolean).join('-')
}
}
diff --git a/packages/design-system/build/utils.js b/packages/design-system/build/utils.js
index c3cf1e3ae69..3a54cc483de 100644
--- a/packages/design-system/build/utils.js
+++ b/packages/design-system/build/utils.js
@@ -41,8 +41,6 @@ exports.cssLoaders = function (options) {
// (which is the case during production build)
if (options.extract) {
loaders.push(MiniCssExtractPlugin.loader)
- } else {
- loaders.push('vue-style-loader')
}
loaders.push(cssLoader)
diff --git a/packages/design-system/build/webpack.base.conf.js b/packages/design-system/build/webpack.base.conf.js
index a16ac9b3cd4..001dc76187b 100644
--- a/packages/design-system/build/webpack.base.conf.js
+++ b/packages/design-system/build/webpack.base.conf.js
@@ -12,36 +12,44 @@ function resolve(dir) {
module.exports = {
mode: process.env.NODE_ENV === 'production' ? config.build.mode : config.dev.mode,
context: path.resolve(__dirname, '../'),
- entry: {
- app: ['./src/system.js']
- },
- output: {
- path: config.build.assetsRoot,
- filename: '[name].js',
- publicPath:
- process.env.NODE_ENV === 'production'
- ? config.build.assetsPublicPath
- : config.dev.assetsPublicPath
- },
resolve: {
- extensions: ['.js', '.vue', '.json'],
+ extensions: ['.js', '.vue', '.json', '.ts'],
alias: {
- vue$: 'vue/dist/vue.esm.js',
+ vue$: 'vue/dist/vue.esm-bundler.js',
'@': resolve('src')
+ },
+ fallback: {
+ url: require.resolve('url/'),
+ path: false,
+ 'process/browser': require.resolve('process/browser')
}
},
module: {
rules: [
+ {
+ test: /\.ts$/,
+ exclude: /node_modules/,
+ use: [
+ {
+ loader: 'ts-loader',
+ options: {
+ appendTsSuffixTo: [/\.vue$/]
+ }
+ }
+ ]
+ },
{
test: /\.vue$/,
- loader: 'vue-loader',
- options: {
- cacheBusting: config.dev.cacheBusting,
- transformAssetUrls: {
- video: ['src', 'poster'],
- source: 'src',
- img: 'src',
- image: 'xlink:href'
+ use: {
+ loader: 'vue-loader',
+ options: {
+ cacheBusting: config.dev.cacheBusting,
+ transformAssetUrls: {
+ video: ['src', 'poster'],
+ source: 'src',
+ img: 'src',
+ image: 'xlink:href'
+ }
}
}
},
@@ -72,45 +80,51 @@ module.exports = {
},
{
test: /\.(png|jpe?g|gif)(\?.*)?$/,
- loader: 'url-loader',
- options: {
- limit: 10000,
- name: utils.assetsPath('img/[name].[hash:7].[ext]')
+ type: 'asset/resource',
+ generator: {
+ filename: 'img/[name].[hash:7][ext]'
}
},
{
test: /\.svg$/,
- loader: 'html-loader'
+ type: 'asset/inline'
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
- loader: 'url-loader',
- options: {
- limit: 10000,
- name: utils.assetsPath('media/[name].[hash:7].[ext]')
+ type: 'asset/resource',
+ generator: {
+ filename: 'media/[name].[hash:7][ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
- loader: 'url-loader',
- options: {
- limit: 10000,
- name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+ type: 'asset/resource',
+ generator: {
+ filename: 'fonts/[name].[hash:7][ext]'
}
+ },
+ {
+ test: /\.(css|scss)$/,
+ use: [
+ process.env.NODE_ENV === 'production' ? MiniCssExtractPlugin.loader : 'style-loader',
+ 'css-loader',
+ 'sass-loader',
+ {
+ loader: 'sass-resources-loader',
+ options: {
+ resources: [
+ path.join(__dirname, '../src/assets/tokens/docs.scss'),
+ path.join(__dirname, '../src/assets/tokens/ods.scss'),
+ path.join(__dirname, '../docs/docs.mixins.scss'),
+ path.join(__dirname, '../docs/docs.functions.scss'),
+ path.join(__dirname, '../docs/docs.spacing.scss'),
+ path.join(__dirname, '../src/styles/styles.scss')
+ ]
+ }
+ }
+ ]
}
]
},
- plugins: [new VueLoaderPlugin(), new MiniCssExtractPlugin({ filename: 'style.css' })],
- node: {
- // prevent webpack from injecting useless setImmediate polyfill because Vue
- // source contains it (although only uses it if it's native).
- setImmediate: false,
- // prevent webpack from injecting mocks to Node native modules
- // that does not make sense for the client
- dgram: 'empty',
- fs: 'empty',
- net: 'empty',
- tls: 'empty',
- child_process: 'empty'
- }
+ plugins: [new VueLoaderPlugin(), new MiniCssExtractPlugin({ filename: 'style.css' })]
}
diff --git a/packages/design-system/changelog/unreleased/bugfix-docs-build b/packages/design-system/changelog/unreleased/bugfix-docs-build
new file mode 100644
index 00000000000..c5d11dceb65
--- /dev/null
+++ b/packages/design-system/changelog/unreleased/bugfix-docs-build
@@ -0,0 +1,6 @@
+Bugfix: Migrate build process of documentation to the latest versions
+
+We've bumped build dependencies of the Design system to support Vue 3 and fix the build of documentation.
+
+https://github.com/owncloud/web/issues/10233
+https://github.com/owncloud/web/pull/10243
diff --git a/packages/design-system/config/docs.config.js b/packages/design-system/config/docs.config.js
index 6bc95071d81..cff29e85693 100644
--- a/packages/design-system/config/docs.config.js
+++ b/packages/design-system/config/docs.config.js
@@ -1,6 +1,5 @@
const path = require('path')
const baseConfig = require('../build/webpack.base.conf.js')
-const { merge } = require('webpack-merge')
const packageConfig = require('../package.json')
const chalk = require('chalk')
@@ -9,6 +8,7 @@ module.exports = {
* Name of your design system. Changes both page title and sidebar logo.
*/
title: 'ownCloud Design System',
+ webpackConfig: baseConfig,
/**
* Most of the styles are defined in /docs/docs.styles.scss
*/
@@ -21,7 +21,6 @@ module.exports = {
monospace: ['Consolas', "'Liberation Mono'", 'Menlo', 'monospace']
}
},
- renderRootJsx: path.join(__dirname, '../docs/components/Preview.js'),
/**
* Define a custom code highlighting theme.
*/
@@ -37,12 +36,13 @@ module.exports = {
* Enabling the below option will break things in ownCloud Design System!
*/
skipComponentsWithoutExample: false,
+ renderRootJsx: '../docs/components/Preview.js',
/**
* We’re defining below JS and SCSS requires for the documentation.
*/
require: [
- path.join(__dirname, '../docs/docs.helper.js'),
- path.join(__dirname, '../docs/docs.styles.scss')
+ path.join(__dirname, '../docs/docs.styles.scss'),
+ path.join(__dirname, '../docs/docs.helper.js')
],
/**
* Enabling the following option splits sections into separate views.
@@ -52,9 +52,6 @@ module.exports = {
{
name: 'Getting Started',
content: '../docs/getting-started.md',
- // Needs to be loaded in somewhere as this is also shown in
- // components overviews.
- components: '../docs/components/status/**/[A-Z]*.vue',
sectionDepth: 1,
exampleMode: 'hide',
usageMode: 'hide'
@@ -86,12 +83,13 @@ module.exports = {
sectionDepth: 1,
exampleMode: 'hide',
usageMode: 'hide',
- components: () => [
- '../docs/components/tokens/IconList.vue',
- '../docs/components/tokens/ColorTokens.vue',
- '../docs/components/tokens/FontSize.vue',
- '../docs/components/tokens/SpacingTokens.vue',
- '../docs/components/tokens/AllTokens.vue'
+ sections: [
+ {
+ name: 'Icons',
+ content: '../docs/icons.md',
+ exampleMode: 'hide',
+ usageMode: 'hide'
+ }
]
},
{
@@ -209,34 +207,6 @@ module.exports = {
'**/*.spec.js',
'**/*.spec.jsx'
],
- webpackConfig: merge(baseConfig, {
- module: {
- rules: [
- {
- test: /\.(css?|scss|sass)(\?.*)?$/,
- use: [
- 'style-loader',
- 'css-loader',
- 'postcss-loader',
- 'sass-loader',
- {
- loader: 'sass-resources-loader',
- options: {
- resources: [
- path.join(__dirname, '../src/assets/tokens/docs.scss'),
- path.join(__dirname, '../src/assets/tokens/ods.scss'),
- path.join(__dirname, '../docs/docs.mixins.scss'),
- path.join(__dirname, '../docs/docs.functions.scss'),
- path.join(__dirname, '../docs/docs.spacing.scss'),
- path.join(__dirname, '../src/styles/styles.scss')
- ]
- }
- }
- ]
- }
- ]
- }
- }),
styleguideDir: '../dist/docs',
printServerInstructions() {},
printBuildInstructions(config) {
diff --git a/packages/design-system/docs/components.md b/packages/design-system/docs/components.md
index 3777e6fef56..71d738f97bc 100644
--- a/packages/design-system/docs/components.md
+++ b/packages/design-system/docs/components.md
@@ -5,5 +5,5 @@ You’re looking at ownCloud Design System’s demo UI Components
.
## Overview
```
-
+
```
diff --git a/packages/design-system/docs/components/Preview.js b/packages/design-system/docs/components/Preview.js
index b128e822442..168cec17721 100644
--- a/packages/design-system/docs/components/Preview.js
+++ b/packages/design-system/docs/components/Preview.js
@@ -1,5 +1,13 @@
-import CodeMirror from 'codemirror'
import CodeTabs from '../utils/tabs.js'
+import { createApp, h } from 'vue'
+import statusLabels from '../utils/statusLabels.js'
+import { createGettext } from 'vue3-gettext'
+import * as directives from '../../src/directives'
+import { EditorView, highlightSpecialChars } from '@codemirror/view'
+import { EditorState } from '@codemirror/state'
+import { html } from '@codemirror/lang-html'
+import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'
+import { tags } from '@lezer/highlight'
function format(node, level) {
const indentBefore = new Array(level++ + 1).join(' ')
@@ -21,11 +29,63 @@ function format(node, level) {
return node
}
+function generateObjectId() {
+ const timestamp = new Date().getTime().toString(16)
+ const randomValue = Math.floor(Math.random() * 1000000).toString(16)
+ const objectId = timestamp + randomValue
+
+ return objectId
+}
+
+// This is a dirty hack to be able to extend the Vue app since vue-styleguidist does not provide any way to do so
+function setupVueApp(element) {
+ const app = createApp(h(element))
+
+ // Components are registered globally only for the styleguidist app...
+ const componentsContext = require.context('../../src/components/', true, /\.vue$/)
+
+ componentsContext.keys().forEach((key) => {
+ const component = componentsContext(key).default
+
+ app.component(component.name, component)
+ })
+
+ app.component('RouterLink', {
+ props: {
+ tag: { type: String, default: 'a' }
+ },
+ render() {
+ return h(this.tag, {}, this.$slots.default)
+ }
+ })
+
+ for (const name in directives) {
+ app.directive(name, directives[name])
+ }
+
+ app.mixin(statusLabels)
+
+ // Vue-gettext is bundled only in the docs. The design system itself depends on the consuming app in providing it
+ app.use(createGettext({ translations: {} }))
+
+ return app
+}
+
export default (previewComponent) => {
// https://vuejs.org/v2/guide/render-function.html
return {
- render(createElement) {
- return createElement(previewComponent)
+ render() {
+ const appId = 'preview-' + generateObjectId()
+ const app = setupVueApp(previewComponent)
+
+ const previewContainer = h('div', {
+ id: appId,
+ onVnodeMounted: () => {
+ app.mount('#' + appId)
+ }
+ })
+
+ return previewContainer
},
mounted() {
CodeTabs.clean()
@@ -45,33 +105,78 @@ export default (previewComponent) => {
const elemText = format(div, 0).innerHTML.replace(/ class=""/g, '')
const elem = document.createElement('div')
- const pre = document.createElement('pre')
const parent = document.querySelector("article div[class^='rsg--tab']")
- pre.appendChild(document.createTextNode(elemText.trim()))
- elem.appendChild(pre)
+
if (parent) {
// Allow some time to pass to make sure codemirror is visible first
setTimeout(() => {
parent.appendChild(elem)
parent.appendChild(tabs)
- CodeMirror(
- function (code) {
- elem.parentNode.replaceChild(code, elem)
- code.className += ' vueds-html vueds-hidden'
- },
+ const themeNight = EditorView.theme(
{
- value: pre.innerText || pre.textContent,
- mode: 'jsx',
- lineNumbers: false,
- lineWrapping: true,
- readOnly: true,
- dragDrop: false,
- theme: 'night',
- viewportMargin: Infinity
- }
+ '&': {
+ color: 'white',
+ backgroundColor: '#041d37',
+ fontSize: '13px',
+ padding: '24px'
+ },
+ '.cm-content': {
+ caretColor: '#ffffff'
+ },
+ '&.cm-focused .cm-cursor': {
+ borderLeftColor: '#ffffff'
+ },
+ '&.cm-focused .cm-selectionBackground, ::selection': {
+ backgroundColor: 'rgba(68, 68, 119, .99)'
+ }
+ },
+ { dark: true }
)
+ const editorState = EditorState.create({
+ doc: elemText.trim(),
+ extensions: [
+ html(),
+ themeNight,
+ EditorState.readOnly.of(true),
+ highlightSpecialChars(),
+ syntaxHighlighting(
+ HighlightStyle.define([
+ {
+ tag: [
+ tags.atom,
+ tags.bool,
+ tags.url,
+ tags.contentSeparator,
+ tags.labelName,
+ tags.attributeValue
+ ],
+ color: '#afe74c'
+ },
+ { tag: tags.string, color: '#afe74c' },
+ { tag: [tags.typeName, tags.namespace, tags.bracket], color: '#54a3f2' },
+ { tag: tags.attributeName, color: '#ffcc4d' }
+ ]),
+ { fallback: false }
+ )
+ ]
+ })
+
+ try {
+ // This code is wrapped in try/catch due to sonarcloud reporting this as issue otherwise
+ // Sonarcloud marks as issues instantiated classes which are not assigned anywhere but we need it like that here due to sideeffects of the class
+ new EditorView({
+ state: editorState,
+ parent: elem
+ })
+ } catch (error) {
+ console.error(error)
+ }
+
+ elem.classList.add('vueds-html')
+ elem.classList.add('vueds-hidden')
+
CodeTabs.init()
}, 300)
}
diff --git a/packages/design-system/docs/components/tokens/AllTokens.spec.js b/packages/design-system/docs/components/tokens/AllTokens.spec.js
deleted file mode 100644
index 773194ee4d6..00000000000
--- a/packages/design-system/docs/components/tokens/AllTokens.spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import Vue from 'vue'
-import AllTokens from './AllTokens.vue'
-
-const Constructor = Vue.extend(AllTokens)
-const vm = new Constructor().$mount()
-
-describe('AllTokens.vue', () => {
- it('should render correct contents', () => {
- expect(vm.$el.querySelector('.token')).toBeDefined()
- })
-
- it('should render multiple tokens', () => {
- expect(vm.$el.querySelectorAll('.token').length).toBeGreaterThan(10)
- })
-
- it('should create code elements for copy pasting', () => {
- expect(vm.$el.querySelector('code.name')).toBeDefined()
- })
-
- it('should create code elements with original values', () => {
- expect(vm.$el.querySelector('code.type')).toBeDefined()
- })
-
- it('should create examples of usage', () => {
- expect(vm.$el.querySelector('.example')).toBeDefined()
- })
-
- it('should apply inline styles', () => {
- expect(vm.$el.querySelector('.example.color').style).toBeDefined()
- })
-})
diff --git a/packages/design-system/docs/components/tokens/ColorTokens.spec.js b/packages/design-system/docs/components/tokens/ColorTokens.spec.js
deleted file mode 100644
index 0bc5a0a802d..00000000000
--- a/packages/design-system/docs/components/tokens/ColorTokens.spec.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import Vue from 'vue'
-import ColorTokens from './ColorTokens.vue'
-
-const Constructor = Vue.extend(ColorTokens)
-const vm = new Constructor().$mount()
-
-describe('ColorTokens.vue', () => {
- it('should render correct contents', () => {
- expect(vm.$el.querySelector('.color')).toBeDefined()
- })
-
- it('should render multiple colors', () => {
- expect(vm.$el.querySelectorAll('.color').length).toBeGreaterThan(2)
- })
-
- it('should create code elements for copy pasting', () => {
- expect(vm.$el.querySelector('.color span')).toBeDefined()
- })
-
- it('should create swatches and apply inline styles', () => {
- expect(vm.$el.querySelector('.color .swatch').style).toBeDefined()
- })
-
- it('should create multiple color groups', () => {
- expect(vm.$el.querySelector('.color_group_2')).toBeDefined()
- })
-})
diff --git a/packages/design-system/docs/components/tokens/FontSize.spec.js b/packages/design-system/docs/components/tokens/FontSize.spec.js
deleted file mode 100755
index c138926bc8e..00000000000
--- a/packages/design-system/docs/components/tokens/FontSize.spec.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import Vue from 'vue'
-import FontSize from './FontSize.vue'
-
-const Constructor = Vue.extend(FontSize)
-const vm = new Constructor().$mount()
-
-describe('FontSize.vue', () => {
- it('should render correct contents', () => {
- expect(vm.$el.querySelector('.font')).toBeDefined()
- })
-
- it('should render multiple sizes', () => {
- expect(vm.$el.querySelectorAll('.font').length).toBeGreaterThan(2)
- })
-
- it('should create px sizes for copy pasting', () => {
- expect(vm.$el.querySelector('.font span')).toBeDefined()
- })
-
- it('should create apply inline styles', () => {
- expect(vm.$el.querySelector('.font').style).toBeDefined()
- })
-})
diff --git a/packages/design-system/docs/components/tokens/SpacingTokens.spec.js b/packages/design-system/docs/components/tokens/SpacingTokens.spec.js
deleted file mode 100644
index 3933cf6a7fd..00000000000
--- a/packages/design-system/docs/components/tokens/SpacingTokens.spec.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import Vue from 'vue'
-import SpacingTokens from './SpacingTokens.vue'
-
-const Constructor = Vue.extend(SpacingTokens)
-const vm = new Constructor().$mount()
-
-describe('SpacingTokens.vue', () => {
- it('should render correct contents', () => {
- expect(vm.$el.querySelector('.space')).toBeDefined()
- })
-
- it('should render multiple sizes', () => {
- expect(vm.$el.querySelectorAll('.space').length).toBeGreaterThan(2)
- })
-
- it('should create px sizes for copy pasting', () => {
- expect(vm.$el.querySelector('.space span')).toBeDefined()
- })
-
- it('should create apply inline styles', () => {
- expect(vm.$el.querySelector('.space').style).toBeDefined()
- })
-})
diff --git a/packages/design-system/docs/docs.helper.js b/packages/design-system/docs/docs.helper.js
index 7144e73c99c..1cee9f0c0ab 100644
--- a/packages/design-system/docs/docs.helper.js
+++ b/packages/design-system/docs/docs.helper.js
@@ -2,17 +2,8 @@
* This is ownCloud Design System’s JS helper file for docs.
* You can add more things if/when needed.
*/
-import Vue from 'vue'
-import statusLabels from './utils/statusLabels'
import activeNav from './utils/activeNav'
import filterSearch from './utils/filterSearch'
-import 'codemirror/mode/jsx/jsx'
-// Vue-gettext is bundled only in the docs. The design system itself depends on the consuming app in providing it
-import GetTextPlugin from 'vue-gettext'
-
-Vue.config.productionTip = false
-Vue.mixin(statusLabels)
-Vue.use(GetTextPlugin, { translations: {} })
document.addEventListener('DOMContentLoaded', () => {
filterSearch.methods.init()
@@ -23,18 +14,3 @@ window.addEventListener('hashchange', () => {
filterSearch.methods.init()
activeNav.methods.init()
})
-
-// mock for the router-link
-Vue.component('RouterLink', {
- props: {
- tag: { type: String, default: 'a' }
- },
- render(createElement) {
- return createElement(this.tag, {}, this.$slots.default)
- }
-})
-
-const directivesContext = require.context('../src/directives/', true, /\.js$/)
-directivesContext.keys().forEach((key) => {
- Vue.directive(directivesContext(key).default.name, directivesContext(key).default)
-})
diff --git a/packages/design-system/docs/docs.spacing.scss b/packages/design-system/docs/docs.spacing.scss
index ae0890d6a4e..132a11bcf04 100644
--- a/packages/design-system/docs/docs.spacing.scss
+++ b/packages/design-system/docs/docs.spacing.scss
@@ -21,7 +21,7 @@ $spacing-ratio: 1.7;
//
// @param {Number} inset-squish-space to set
@mixin inset-squish-space($value) {
- padding: round($value / $spacing-ratio - 1px) $value round($value / $spacing-ratio);
+ padding: round(calc($value / $spacing-ratio) - 1px) $value round(calc($value / $spacing-ratio));
}
// Create stack-space
@@ -44,4 +44,4 @@ $spacing-ratio: 1.7;
&:last-child {
margin-right: 0;
}
-}
+}
\ No newline at end of file
diff --git a/packages/design-system/docs/docs.styles.scss b/packages/design-system/docs/docs.styles.scss
index 4cb4096d132..2258649e08d 100644
--- a/packages/design-system/docs/docs.styles.scss
+++ b/packages/design-system/docs/docs.styles.scss
@@ -37,7 +37,8 @@ div.rsg--root-1 {
// Main content
main[class^="rsg--content"] {
- display: block; /* IE11 fix */
+ display: block;
+ /* IE11 fix */
padding: $space-s $space-xl;
background-color: tint($docs-grey, 90%);
@@ -47,14 +48,14 @@ main[class^="rsg--content"] {
}
// Resetting margins for Styleguidist
-header[class^="rsg--header"] > div[class^="rsg--wrapper"],
-section > div[class^="rsg--wrapper"] + article[class^="rsg--root"],
+header[class^="rsg--header"]>div[class^="rsg--wrapper"],
+section>div[class^="rsg--wrapper"]+article[class^="rsg--root"],
article[class^="rsg--root"] div[class^="rsg--root"] {
margin: 0 !important;
}
// Display rsg--roots as flex
-main section section > div > div[class^="rsg--root"] {
+main section section>div>div[class^="rsg--root"] {
display: flex;
flex-direction: column;
}
@@ -65,6 +66,7 @@ main section section > div > div[class^="rsg--root"] {
// Link color
div[class^="rsg--root"] a[class^="rsg--link"] {
color: $color-bleu-de-france;
+
&:hover {
color: $color-bleu-de-france-dark;
}
@@ -72,8 +74,8 @@ div[class^="rsg--root"] a[class^="rsg--link"] {
// Main headings
// (includes h2 as well since in component views that’s the first heading)
-div[class^="rsg--wrapper"] > h1[class^="rsg--heading"],
-div[class^="rsg--wrapper"] > h2[class^="rsg--heading"] {
+div[class^="rsg--wrapper"]>h1[class^="rsg--heading"],
+div[class^="rsg--wrapper"]>h2[class^="rsg--heading"] {
display: block;
border: 0;
line-height: $oc-docs-line-height-small;
@@ -82,15 +84,18 @@ div[class^="rsg--wrapper"] > h2[class^="rsg--heading"] {
margin: -#{$space-s} -#{$space-xl} $space-l -#{$space-xl};
background: $color-cloud;
font-size: $size-xxl;
+
a:hover {
text-decoration: none;
cursor: default;
}
+
@media (max-width: 1300px) {
padding: $space-l $space-xl;
}
+
@media (max-width: #{$docs-breakpoint}) {
- font-size: $size-xl / 1.2;
+ font-size: calc($size-xl / 1.2);
width: calc(100% + #{$space-xl});
padding: $space-l $space-m;
margin: -#{$space-s} -#{$space-m} $space-m;
@@ -103,10 +108,11 @@ header[class^="rsg--header"] {
}
// Links inside h1
-div[class^="rsg--wrapper"] > h1[class^="rsg--heading"] a {
+div[class^="rsg--wrapper"]>h1[class^="rsg--heading"] a {
font-weight: $oc-docs-font-weight-normal;
color: $color-oxford-blue;
letter-spacing: -1px;
+
&:hover {
text-decoration: none;
cursor: default;
@@ -123,12 +129,15 @@ h2[class^="rsg--heading"] {
font-weight: $oc-docs-font-weight-normal;
letter-spacing: -0.5px;
width: 100%;
+
@media (max-width: #{$docs-breakpoint}) {
- font-size: $size-xl / 1.3;
+ font-size: calc($size-xl / 1.3);
}
+
@media (max-width: #{$docs-breakpoint-small}) {
- font-size: $size-xl / 1.6;
+ font-size: calc($size-xl / 1.6);
}
+
a {
color: $docs-color-heading;
}
@@ -144,8 +153,9 @@ h3[class^="rsg--heading"] a {
margin: 0 0 $space-l;
font-size: $size-l;
color: $docs-color-text;
+
@media (max-width: #{$docs-breakpoint}) {
- font-size: $size-l / 1.2;
+ font-size: calc($size-l / 1.2);
margin: 0 0 $space-m;
}
}
@@ -168,9 +178,11 @@ p[class^="rsg--para"] {
color: $docs-color-text;
margin-bottom: $space-s;
line-height: $oc-docs-line-height-medium;
+
strong a[class^="rsg--link"] {
font-weight: $oc-docs-font-weight-semi-bold;
}
+
code {
-webkit-font-smoothing: subpixel-antialiased;
-moz-osx-font-smoothing: auto;
@@ -180,6 +192,7 @@ p[class^="rsg--para"] {
border-radius: $oc-docs-border-radius-default;
font-size: 87.5%;
}
+
a {
overflow-wrap: break-word;
word-wrap: break-word;
@@ -188,7 +201,8 @@ p[class^="rsg--para"] {
-webkit-hyphens: auto;
hyphens: auto;
}
- pre + & {
+
+ pre+& {
margin-top: $space-s;
}
}
@@ -200,9 +214,11 @@ h3[class^="rsg--heading"],
h4[class^="rsg--heading"] {
max-width: 800px;
width: 75%;
+
p[class^="rsg--para"] {
width: 100%;
}
+
@media (max-width: 1300px) {
width: 100%;
}
@@ -220,6 +236,7 @@ td[class^="rsg--cell"] p {
div[class^="rsg--logo"] {
@include inset-space($space-m);
border-bottom: 1px solid rgba($color-white, 0.1);
+
h1 {
color: tint($color-bleu-de-france, 90%);
font-weight: $oc-docs-font-weight-normal;
@@ -248,21 +265,27 @@ div[class^="rsg--search"] input {
color: $color-white;
border: 1px solid transparent;
background: mix($color-bleu-de-france, $color-rich-black, 20%);
+
&:focus {
border: 1px solid $color-bleu-de-france;
+
&::-webkit-textfield-decoration-container {
display: none !important;
}
+
&::-webkit-contacts-auto-fill-button {
display: none !important;
}
}
+
&::-webkit-input-placeholder {
color: rgba(mix($color-white, $color-bleu-de-france, 50%), 0.35);
}
+
&:-ms-input-placeholder {
color: rgba(mix($color-white, $color-bleu-de-france, 50%), 0.35);
}
+
&::-moz-placeholder {
color: rgba(mix($color-white, $color-bleu-de-france, 50%), 0.35);
opacity: 1;
@@ -273,6 +296,7 @@ div[class^="rsg--search"] input {
div[class^="rsg--sidebar"] {
background: mix($color-bleu-de-france, $color-rich-black, 5%);
border: 0;
+
@media (max-width: #{$docs-breakpoint}) {
padding-bottom: $space-l;
}
@@ -280,6 +304,7 @@ div[class^="rsg--sidebar"] {
// Sidebar sub navigations
ul ul[class^="rsg--list"] {
display: none;
+
&.vueds-visible {
display: block;
}
@@ -302,21 +327,25 @@ div[class^="rsg--sidebar"] {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+
&:hover {
color: $color-bleu-de-france-lighter;
}
+
&:active {
color: $color-bleu-de-france-dark;
}
}
// Sidebar active link
- .vueds-active, li[class*="rsg--isSelected-"] {
+ .vueds-active,
+ li[class*="rsg--isSelected-"] {
ul[class^="rsg--list"] {
display: block;
}
- & > a,
- & > a:hover {
+
+ &>a,
+ &>a:hover {
color: tint($color-bleu-de-france, 80%);
}
}
@@ -329,6 +358,7 @@ div[class^="rsg--sidebar"] {
ul {
padding-left: $space-s;
line-height: $oc-docs-line-height-small;
+
@media (max-width: #{$docs-breakpoint-small}) {
padding: 0 0 0 $space-l;
width: 90%;
@@ -346,6 +376,7 @@ div[class^="rsg--sidebar"] {
font-weight: $oc-docs-font-weight-normal;
-webkit-font-smoothing: subpixel-antialiased;
-moz-osx-font-smoothing: auto;
+
@media (max-width: #{$docs-breakpoint-small}) {
float: left;
padding: 0 $space-xs 0 0;
@@ -360,7 +391,7 @@ div[class^="rsg--sidebar"] {
// Previews of the components
div[class^="rsg--preview"] {
- padding: $space-l / 1.2;
+ padding: calc($space-l / 1.2);
background-color: $color-white;
border: 1px solid tint($docs-grey, 50%);
box-shadow: inset 0 0 $space-xs rgba($color-rich-black, 0.05);
@@ -381,7 +412,7 @@ div[data-preview="Elements"] {
padding: 0;
// This hides code previews from the above examples
- & + div + div[class^="rsg--tab"] {
+ &+div+div[class^="rsg--tab"] {
display: none !important;
}
}
@@ -399,13 +430,13 @@ table[class^="rsg--table"] {
margin-bottom: $space-s;
overflow-x: auto;
}
+
thead[class^="rsg--tableHead"] {
border: 0;
}
// Codemirror and markdown code blocks
pre[class^="rsg--pre"],
-.vueds-html.cm-s-night.CodeMirror,
.react-codemirror2 .CodeMirror.CodeMirror {
background: mix($color-bleu-de-france, $color-rich-black, 10%);
border-bottom-left-radius: $oc-docs-border-radius-default;
@@ -418,30 +449,28 @@ pre[class^="rsg--pre"],
font-family: Consolas, "Liberation Mono", Menlo, monospace;
font-size: $size-s;
margin: 0;
- min-height: $space-xxl / 1.5;
+ min-height: calc($space-xxl / 1.5);
margin-bottom: $space-m;
color: $color-white;
padding: $space-m;
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
+
.CodeMirror-scroll,
.CodeMirror-vscrollbar {
overflow: hidden;
}
+
code {
color: $color-white;
}
}
-// HTML preview needs some padding adjustments to match Styleguidist
-.vueds-html.cm-s-night.CodeMirror {
- padding-left: $space-m - 4px;
-}
-
// VUE & HTML Code tabs
div[class^="rsg--tab"] {
position: relative;
+
.vueds-tabs {
z-index: 5;
border-radius: $oc-docs-border-radius-default;
@@ -450,6 +479,7 @@ div[class^="rsg--tab"] {
position: absolute;
top: $space-m;
right: $space-m;
+
.vueds-tab {
border: 0;
margin: 0;
@@ -462,12 +492,15 @@ div[class^="rsg--tab"] {
cursor: pointer;
background: mix($color-bleu-de-france, $color-rich-black, 50%);
color: $color-white;
+
&:active {
background: mix($color-bleu-de-france, $color-rich-black, 45%);
}
+
&:focus {
outline: none;
}
+
&--active {
background: mix($color-bleu-de-france, $color-rich-black, 40%);
box-shadow: inset 0 2px 8px rgba($color-rich-black, 0.2);
@@ -502,6 +535,7 @@ div[class^="rsg--tab"] {
.hljs-name {
color: $color-bleu-de-france-light !important;
}
+
.hljs-attribute,
.hljs-keyword,
.hljs-attr,
@@ -510,6 +544,7 @@ div[class^="rsg--tab"] {
.cm-s-night span.cm-attribute {
color: $color-ucla-gold-light !important;
}
+
.cm-s-night span.cm-string,
.hljs-string {
color: lighten($docs-status-ready, 20%) !important;
@@ -520,11 +555,13 @@ span[class^="rsg--type"],
code[class^="rsg--code"] {
color: $color-silver;
}
+
span[class^="rsg--name"] code[class^="rsg--code"],
code.name {
font-weight: $oc-docs-font-weight-bold;
color: shade($color-silver, 50%);
}
+
span[class^="rsg--type"] code[class^="rsg--code"],
code.type {
background: tint($docs-grey, 75%);
@@ -540,11 +577,13 @@ code.type {
header[class^="rsg--header"] {
order: 2;
}
+
div[class^="rsg--docs"],
article[class^="rsg--root"],
button[class^="rsg--button"] {
order: 3;
}
+
div[class^="rsg--root"] div[class^="rsg--tabs"] {
order: 4;
}
@@ -558,7 +597,7 @@ div[class^="rsg--root"] div[class^="rsg--tabs"] {
cursor: help;
line-height: $oc-docs-line-height-xsmall;
background: tint($docs-grey, 50%);
- padding: $space-xs $space-s $space-xs/1.2;
+ padding: $space-xs $space-s calc($space-xs / 1.2);
text-transform: uppercase;
letter-spacing: 1px;
font-size: $size-xs;
@@ -568,26 +607,32 @@ div[class^="rsg--root"] div[class^="rsg--tabs"] {
right: $space-xl;
top: $space-xl * 1.2;
z-index: 2;
+
@media (max-width: 1300px) {
top: $space-xl;
}
+
@media (max-width: #{$docs-breakpoint}) {
top: $space-l * 1.2;
right: $space-m;
}
+
&-ready {
background: $docs-status-ready;
color: $color-white;
}
+
&-review,
&-under-review {
background: $color-ucla-gold;
color: $color-rich-black;
}
+
&-prototype {
background: $color-bleu-de-france;
color: $color-white;
}
+
&-deprecated {
background: $color-vermilion;
color: $color-white;
@@ -620,22 +665,27 @@ table[class^="rsg--table"] {
color: tint($color-oxford-blue, 10%);
text-align: left;
}
+
th[class^="rsg--cellHeading"],
td {
padding: $space-s $space-l $space-s $space-s;
background: transparent;
}
+
td {
font-size: $size-m;
padding: $space-s $space-l $space-s $space-s;
+
&:first-child {
font-weight: $oc-docs-font-weight-bold;
white-space: nowrap;
}
}
+
tr {
border-bottom: 1px solid tint($docs-grey, 50%);
}
+
tbody tr:last-child {
border-bottom: 0;
}
@@ -646,6 +696,7 @@ thead[class^="rsg--thead"] {
border-top-left-radius: $oc-docs-border-radius-default;
border-bottom-left-radius: $oc-docs-border-radius-default;
}
+
th:last-child {
border-top-right-radius: $oc-docs-border-radius-default;
border-bottom-right-radius: $oc-docs-border-radius-default;
@@ -668,9 +719,9 @@ div[class^="rsg--toolbar"] {
// Hide private components
.hide-private,
-.hide-private + div,
+.hide-private+div,
a[href="/#/Private%20Components"],
-a[href="/#/Private%20Components"] + ul {
+a[href="/#/Private%20Components"]+ul {
display: none !important;
}
@@ -686,4 +737,4 @@ ul a[href*="/#/Private%20Components"] {
.oc-docs-width-medium {
width: 300px
-}
+}
\ No newline at end of file
diff --git a/packages/design-system/docs/getting-started.md b/packages/design-system/docs/getting-started.md
index be2d0a92074..0baf9d69e1c 100644
--- a/packages/design-system/docs/getting-started.md
+++ b/packages/design-system/docs/getting-started.md
@@ -5,5 +5,5 @@ You’re looking at [ownCloud Design System’s](https://owncloud.github.io/ownc
## System Overview
```
-
+
```
diff --git a/packages/design-system/docs/icons.md b/packages/design-system/docs/icons.md
new file mode 100644
index 00000000000..18067d756db
--- /dev/null
+++ b/packages/design-system/docs/icons.md
@@ -0,0 +1,6 @@
+All known icons in the ownCloud Design System
+Icons made by [Remixicon](https://remixicon.com/) and, in the case of the `resource-type-*` icons, [Font Awesome](https://fontawesome.com/) (available under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license).
+
+```vue
+
+```
diff --git a/packages/design-system/docs/tokens.md b/packages/design-system/docs/tokens.md
index 37a2e0a154a..067075dff9e 100644
--- a/packages/design-system/docs/tokens.md
+++ b/packages/design-system/docs/tokens.md
@@ -5,23 +5,23 @@ You’re looking at ownCloud Design System’s demo design tokens
.
## Color Palette
```
-
+
```
## Font Sizes
```
-
+
```
## Spacing
```
-
+
```
## All Tokens
```
-
+
```
diff --git a/packages/design-system/package.json b/packages/design-system/package.json
index 73211f0f940..9f4ec6dc267 100644
--- a/packages/design-system/package.json
+++ b/packages/design-system/package.json
@@ -45,14 +45,18 @@
"@babel/plugin-transform-runtime": "7.23.7",
"@babel/preset-env": "7.23.7",
"@babel/runtime": "7.23.7",
+ "@codemirror/lang-html": "^6.4.7",
+ "@codemirror/language": "^6.10.0",
+ "@codemirror/state": "^6.4.0",
+ "@codemirror/view": "^6.23.0",
+ "@lezer/highlight": "^1.2.0",
"@popperjs/core": "^2.11.5",
"autoprefixer": "10.4.16",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "29.5.0",
"babel-loader": "^9.0.0",
"babel-plugin-require-context-hook": "^1.0.0",
- "chalk": "^4.1.0",
- "codemirror": "^6.0.0",
+ "chalk": "^4.1.2",
"compression-webpack-plugin": "^10.0.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "6.8.1",
@@ -77,45 +81,50 @@
"optimize-css-assets-webpack-plugin": "^6.0.1",
"postcss-import": "16.0.0",
"postcss-loader": "7.3.4",
+ "postcss-nested": "^6.0.1",
"postcss-safe-parser": "7.0.0",
+ "postcss-simple-vars": "^7.0.1",
"postcss-url": "10.1.3",
"prettier": "^3.0.0",
"process": "^0.11.10",
- "react": "^18.0.0",
- "react-dom": "^18.0.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
"rimraf": "^3.0.2",
- "sass": "1.62.1",
- "sass-loader": "^10.1.0",
- "sass-resources-loader": "^2.0.1",
+ "sass": "1.69.7",
+ "sass-loader": "10.1.0",
+ "sass-resources-loader": "^2.2.5",
"semver": "7.5.4",
"shelljs": "^0.8.3",
- "style-dictionary": "^3.0.0-rc.8",
+ "style-dictionary": "^3.9.1",
"style-loader": "^2.0.0",
"style-value-types": "^5.0.0",
"stylelint": "15.11.0",
"stylelint-config-sass-guidelines": "^10.0.0",
"stylelint-config-standard": "^34.0.0",
- "tinycolor2": "^1.4.2",
+ "tinycolor2": "^1.6.0",
"tippy.js": "^6.3.7",
+ "ts-loader": "^9.5.1",
"typescript": "5.3.3",
+ "url": "^0.11.3",
"url-loader": "^4.1.1",
"v-calendar": "github:dschmidt/v-calendar#3ce6e3b8afd5491cb53ee811281d5fa8a45b044d",
"vue": "3.3.8",
"vue-inline-svg": "3.1.2",
- "vue-loader": "^15.9.0",
+ "vue-loader": "^17.4.2",
"vue-router": "4.2.5",
"vue-select": "4.0.0-beta.6",
- "vue-style-loader": "^4.1.2",
- "vue-styleguidist": "^4.44.2",
+ "vue-style-loader": "^4.1.3",
+ "vue-styleguidist": "^4.72.4",
"vue3-gettext": "2.4.0",
"web-test-helpers": "workspace:*",
"webfontloader": "^1.6.28",
- "webpack": "^4.41.6",
- "webpack-bundle-analyzer": "^4.2.0",
- "webpack-merge": "^5.4.0",
- "webpack-merge-and-include-globally": "^2.1.24",
+ "webpack": "^5.89.0",
+ "webpack-bundle-analyzer": "^4.10.1",
+ "webpack-dev-server": "^4.15.1",
+ "webpack-merge": "^5.10.0",
+ "webpack-merge-and-include-globally": "^2.3.4",
"webpack-node-externals": "^3.0.0",
- "yaml": "^2.0.0"
+ "yaml": "^2.3.4"
},
"peerDependencies": {
"@popperjs/core": "^2.11.5",
@@ -129,11 +138,10 @@
"vue": "3.3.8",
"vue-inline-svg": "3.1.2",
"vue-select": "^3.12.0",
- "webfontloader": "^1.6.28",
- "portal-vue": "*"
+ "webfontloader": "^1.6.28"
},
"engines": {
"node": ">= 14.0.0",
"npm": ">= 3.0.0"
}
-}
+}
\ No newline at end of file
diff --git a/packages/design-system/src/components/OcApplicationIcon/OcApplicationIcon.vue b/packages/design-system/src/components/OcApplicationIcon/OcApplicationIcon.vue
index 653dfdb8922..07ad5d307ea 100644
--- a/packages/design-system/src/components/OcApplicationIcon/OcApplicationIcon.vue
+++ b/packages/design-system/src/components/OcApplicationIcon/OcApplicationIcon.vue
@@ -107,13 +107,13 @@ export default defineComponent({
```js
-No color: (color will be hash generated by icon name)
+// No color: (color will be hash generated by icon name)
-With primary color:
+// With primary color:
-With primary and secondary color:
+// With primary and secondary color:
```
diff --git a/packages/design-system/src/components/OcAvatars/__snapshots__/OcAvatars.spec.ts.snap b/packages/design-system/src/components/OcAvatars/__snapshots__/OcAvatars.spec.ts.snap
index a0b58ccb915..b97ab61ffb9 100644
--- a/packages/design-system/src/components/OcAvatars/__snapshots__/OcAvatars.spec.ts.snap
+++ b/packages/design-system/src/components/OcAvatars/__snapshots__/OcAvatars.spec.ts.snap
@@ -2,39 +2,21 @@
exports[`OcAvatars displays tooltip 1`] = `
-
-
-
-
-
-
+
List of users
`;
exports[`OcAvatars prefers avatars over links when maxDisplayed is exceeded 1`] = `
-
-
-
-
-
-
-
+
List of users
`;
exports[`OcAvatars shows avatars first and links last 1`] = `
-
-
-
-
-
-
-
-
+
List of users
`;
diff --git a/packages/design-system/src/components/OcModal/OcModal.vue b/packages/design-system/src/components/OcModal/OcModal.vue
index 98e81417e5f..bae7075888e 100644
--- a/packages/design-system/src/components/OcModal/OcModal.vue
+++ b/packages/design-system/src/components/OcModal/OcModal.vue
@@ -77,7 +77,7 @@