diff --git a/frontend/src/components/BlueScreen.vue b/frontend/src/components/BlueScreen.vue new file mode 100644 index 0000000..706131b --- /dev/null +++ b/frontend/src/components/BlueScreen.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/frontend/src/components/BootSequence.vue b/frontend/src/components/BootSequence.vue new file mode 100644 index 0000000..c8a27df --- /dev/null +++ b/frontend/src/components/BootSequence.vue @@ -0,0 +1,622 @@ + + + + + diff --git a/frontend/src/components/Win98Window.vue b/frontend/src/components/Win98Window.vue new file mode 100644 index 0000000..d1aa5c0 --- /dev/null +++ b/frontend/src/components/Win98Window.vue @@ -0,0 +1,603 @@ + + + + + diff --git a/frontend/src/composables/useWizardNav.js b/frontend/src/composables/useWizardNav.js new file mode 100644 index 0000000..73d2277 --- /dev/null +++ b/frontend/src/composables/useWizardNav.js @@ -0,0 +1,36 @@ +import { inject, provide, ref } from 'vue' + +const KEY = Symbol('wizardNav') + +/** + * Called once in WizardLayout to create the shared nav state. + */ +export function provideWizardNav() { + const nav = ref({ + // ← Back + backLabel: '< Back', + backDisabled: false, + onBack: null, // null = disabled + + // Next → + nextLabel: 'Next >', + nextDisabled: false, + onNext: null, // null = disabled + + // Finish (final action — Extract & Push, Done, etc.) + finishLabel: 'Finish', + finishDisabled: false, + onFinish: null, // null = disabled + }) + provide(KEY, nav) + return nav +} + +/** + * Called in each page component to register its nav handlers. + * Any field omitted keeps its previous value; pass null for a + * handler to disable that button. + */ +export function useWizardNav() { + return inject(KEY) +} diff --git a/frontend/src/css/app.scss b/frontend/src/css/app.scss index 5da4a0f..4f844fa 100644 --- a/frontend/src/css/app.scss +++ b/frontend/src/css/app.scss @@ -1 +1,167 @@ // app global css / scss goes here + +// ── Shared page chrome (inside WizardLayout) ─────────────────────── + +.wiz-page { + display: flex; + flex-direction: column; + height: 100%; + font-size: 12px; + + // Header banner — Win98 dialog title area + &__head { + flex-shrink: 0; + display: flex; + align-items: flex-start; + gap: 12px; + padding: 14px 18px 12px; + background: #fff; + border-bottom: 2px solid; + border-color: #808080 #fff #fff #808080; + } + + &__head-icon { font-size: 28px; flex-shrink: 0; margin-top: 2px; } + &__head-text { flex: 1; } + + &__step-label { + font-size: 10px; + font-weight: 700; + letter-spacing: 0.8px; + text-transform: uppercase; + color: #808080; + margin-bottom: 3px; + } + + &__title { + font-size: 15px; + font-weight: 700; + color: $primary; // #011826 + margin: 0 0 3px; + line-height: 1.2; + } + + &__desc { + font-size: 11px; + color: #444; + margin: 0; + line-height: 1.5; + } + + &__body { + flex: 1; + overflow-y: auto; + padding: 14px 18px; + } + + &__nav { display: none; } // nav lives in the window footer +} + +// ── Win98 inset panel ───────────────────────────────────────────── +.w98-panel { + border: 2px solid; + border-color: #808080 #fff #fff #808080; + background: #fff; + + &__head { + padding: 3px 8px; + background: #F2F2F2; + font-size: 11px; + font-weight: 700; + color: $primary; + border-bottom: 1px solid #808080; + display: flex; + align-items: center; + gap: 5px; + text-transform: uppercase; + letter-spacing: 0.5px; + } + + &__body { padding: 10px; } +} + +// ── Win98 Explorer list ─────────────────────────────────────────── +.w98-list { + border: 2px solid; + border-color: #808080 #fff #fff #808080; + background: #fff; +} + +.w98-list-row { + display: flex; + align-items: center; + gap: 10px; + padding: 5px 8px; + border-bottom: 1px solid #ececec; + cursor: pointer; + font-size: 12px; + + &:last-child { border-bottom: none; } + + &:hover { + background: $secondary; // #168C40 + color: #fff; + + .w98-list-row__meta { color: rgba(255,255,255,0.7); } + } + + &__name { flex: 1; font-size: 12px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; } + &__meta { font-size: 11px; color: #808080; flex-shrink: 0; } +} + +// ── Field label ─────────────────────────────────────────────────── +.w98-field-label { + font-size: 11px; + font-weight: 700; + margin-bottom: 4px; + color: #000; +} + +// ── Win98 inset select ──────────────────────────────────────────── +.w98-select { + height: 21px; + padding: 0 4px; + font-family: 'Tahoma', 'MS Sans Serif', Arial, sans-serif; + font-size: 12px; + border: none; + box-shadow: + inset 1px 1px #0a0a0a, + inset -1px -1px #ffffff, + inset 2px 2px #808080, + inset -2px -2px #e8e8e8; + background: #fff; + cursor: pointer; + + &--full { width: 100%; } + + &:disabled { color: #808080; cursor: default; } +} + +// ── Win98 inset text input ──────────────────────────────────────── +.w98-input-full { + width: 100%; + height: 21px; + padding: 2px 4px; + font-family: 'Tahoma', 'MS Sans Serif', Arial, sans-serif; + font-size: 12px; + border: none; + box-shadow: + inset 1px 1px #0a0a0a, + inset -1px -1px #ffffff, + inset 2px 2px #808080, + inset -2px -2px #e8e8e8; + background: #fff; + box-sizing: border-box; +} + +// ── Inline link-style button (footer "Sign out") ────────────────── +.w98-link-btn { + background: none; + border: none; + padding: 0; + font-size: inherit; + color: $primary; + text-decoration: underline; + cursor: pointer; + + &:hover { color: $secondary; } +} diff --git a/frontend/src/css/quasar.variables.scss b/frontend/src/css/quasar.variables.scss index 39df4d1..298c365 100644 --- a/frontend/src/css/quasar.variables.scss +++ b/frontend/src/css/quasar.variables.scss @@ -12,18 +12,21 @@ // to match your app's branding. // Tip: Use the "Theme Builder" on Quasar's documentation website. -// Brand colors derived from the git-extract organization logo: -// Navy #1e2e4a — browser window, git graph, wordmark -// Green #2ea84e — arrow and folder icon +// Brand palette +// #011826 darkest navy — primary surfaces, title bar, sidebar +// #168C40 forest green — actions, active step, success +// #6BBF89 sage green — accent, hover, done steps +// #A7D9B8 pale green — subtle highlights +// #F2F2F2 off-white — window chrome, panel backgrounds -$primary: #1e2e4a; // brand navy -$secondary: #2ea84e; // brand green -$accent: #4cc474; // lighter green (hover / highlight) +$primary: #011826; // darkest navy +$secondary: #168C40; // forest green +$accent: #6BBF89; // sage green -$dark: #1a2540; // deep navy for dark-mode surfaces -$dark-page: #111b30; // near-black navy for dark-mode page background +$dark: #011826; // same as primary +$dark-page: #010f18; // near-black for dark mode -$positive: #28a745; // green — success (same family as brand green) -$negative: #c10015; // red — error -$info: #1799b5; // blue-teal — informational -$warning: #f2c037; // amber — warning +$positive: #168C40; // green — success +$negative: #c10015; // red — error +$info: #6BBF89; // sage — informational +$warning: #f2c037; // amber — warning diff --git a/frontend/src/layouts/WizardLayout.vue b/frontend/src/layouts/WizardLayout.vue new file mode 100644 index 0000000..f122d72 --- /dev/null +++ b/frontend/src/layouts/WizardLayout.vue @@ -0,0 +1,249 @@ + + + + + diff --git a/frontend/src/pages/ExtractFinishPage.vue b/frontend/src/pages/ExtractFinishPage.vue new file mode 100644 index 0000000..1c933ea --- /dev/null +++ b/frontend/src/pages/ExtractFinishPage.vue @@ -0,0 +1,189 @@ + + + + + diff --git a/frontend/src/pages/ExtractOptionsPage.vue b/frontend/src/pages/ExtractOptionsPage.vue new file mode 100644 index 0000000..9c50f59 --- /dev/null +++ b/frontend/src/pages/ExtractOptionsPage.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/frontend/src/pages/ExtractPage.vue b/frontend/src/pages/ExtractPage.vue index 600f925..896690b 100644 --- a/frontend/src/pages/ExtractPage.vue +++ b/frontend/src/pages/ExtractPage.vue @@ -1,115 +1,150 @@