- Migrate `StatefulVue`:
- Introduce `UseCollectionState` that replaces its behavior and acts
as a shared state store.
- Add more encapsulated, granular functions based on read or write
access to state in CollectionState.
- Some linting rules get activates due to new code-base compability to
modern parses, fix linting errors.
- Rename Dialog to ModalDialog as after refactoring,
eslintvue/no-reserved-component-names does not allow name Dialog.
- To comply with `vue/multi-word-component-names`, rename:
- `Code` -> `CodeInstruction`
- `Handle` -> `SliderHandle`
- `Documentable` -> `DocumentableNode`
- `Node` -> `NodeContent`
- `INode` -> `INodeContent`
- `Responsive` -> `SizeObserver`
- Remove `vue-property-decorator` and `vue-class-component`
dependencies.
- Refactor `watch` with computed properties when possible for cleaner
code.
- Introduce `UseApplication` to reduce repeated code in new components
that use `computed` more heavily than before.
- Change TypeScript target to `es2017` to allow top level async calls
for getting application context/state/instance to simplify the code by
removing async calls. However, mocha (unit and integration) tests do
not run with top level awaits, so a workaround is used.
7.1 KiB
Presentation layer
The presentation layer handles UI concerns using Vue as JavaScript framework and Electron to provide desktop functionality.
It reflects the application state and allows user interactions to modify it. Components manage their own local UI state.
The presentation layer uses an event-driven architecture for bidirectional reactivity between the application state and UI. State change events flow bottom-up to trigger UI updates, while user events flow top-down through components, some ultimately modifying the application state.
📖 Refer to architecture.md (Layered Application) to read more about the layered architecture.
Structure
/src/presentation/: Contains all presentation related code including Vue and Electron configurationsbootstrapping/: Registers Vue global objects including components and plugins.components/: Contains all Vue components and their helper classes.assets/: Contains assets that webpack will process.fonts/: Contains fontsstyles/: Contains shared styles used throughout different components.components/: Contains reusable styles coupled to a Vue/HTML component.vendors-extensions/: Contains styles that override third-party components used.main.scss: Primary Sass file, passes along all other styles, should be the single file used from other components.
main.ts: Application entry point that mounts and starts Vue application.electron/: Electron configuration for the desktop application.main.ts: Main process of Electron, started as first thing when app starts.
/public/: Contains static assets that are directly copied and do not go through webpack./vue.config.js: Global Vue CLI configurations loaded by@vue/cli-service./postcss.config.js: PostCSS configurations used by Vue CLI internally./babel.config.js: Babel configurations for polyfills used by@vue/cli-plugin-babel.
Visual design best-practices
Add visual clues for clickable items. It should be as clear as possible that they're interactable at first look without hovering. They should also have different visual state when hovering/touching on them that indicates that they are being clicked, which helps with accessibility.
Application data
Components (should) use UseApplication to reach the application domain to avoid parsing and compiling the application again.
Application.ts is an immutable domain model that represents application state. It includes:
- available scripts, collections as defined in collection files,
- package information as defined in
package.json.
You can read more about how application layer provides application data to he presentation in application.md | Application data.
Application state
This project uses a singleton instance of the application state, making it available to all Vue components.
The decision to not use third-party state management libraries like vuex or pinia was made to promote code independence and enhance portability.
Stateful components can mutate and/or react to state changes (e.g., user selection, search queries) in the ApplicationContext. Vue components import CollectionState.ts to access both the application context and the state.
CollectionState.ts provides several functionalities including:
- Singleton State Instance: It creates a singleton instance of the state, which is shared across the presentation layer. The singleton instance ensures that there's a single source of truth for the application's state.
- State Change Callback and Lifecycle Management: It offers a mechanism to register callbacks, which will be invoked when the state initializes or mutates. It ensures that components unsubscribe from state events when they are no longer in use or when ApplicationContext switches the active collection.
- State Access and Modification: It provides functions to read and mutate for accessing and modifying the state, encapsulating the details of these operations.
- Event Subscription Lifecycle Management: Includes an
eventsmember that simplifies state subscription lifecycle events. This ensures that components unsubscribe from state events when they are no longer in use, or when ApplicationContext switches the active collection.
📖 Refer to architecture.md | Application State for an overview of event handling and application.md | Application State for an in-depth understanding of state management in the application layer.
Modals
ModalDialog.vue is a shared component utilized for rendering modal windows.
Use the component by wrapping the desired content within its slot and calling the .show() function on its reference, as shown below:
<ModalDialog ref="testDialog">
<div>Hello world</div>
</ModalDialog>
<div @click="$refs.testDialog.show()">Show dialog</div>
Sass naming convention
- Use lowercase for variables/functions/mixins, e.g.:
- Variable:
$variable: value; - Function:
@function function() {} - Mixin:
@mixin mixin() {}
- Variable:
- Use - for a phrase/compound word, e.g.:
- Variable:
$some-variable: value; - Function:
@function some-function() {} - Mixin:
@mixin some-mixin() {}
- Variable:
- Grouping and name variables from generic to specific, e.g.:
- ✅
$border-blue,$border-blue-light,$border-blue-lightest,$border-red - ❌
$blue-border,$light-blue-border,$lightest-blue-border,$red-border
- ✅