feat(guides): add navigation after save and update UI styling

- Add programmatic navigation to the guide view after successful form submission.
- Add class names and layout styling for header, navigation sidebar, and action buttons.
- Update Guide view print layout.
This commit is contained in:
johannes-hernehult 2026-06-30 11:49:10 +02:00
parent 03df525775
commit ab2029384b
5 changed files with 89 additions and 14 deletions

View file

@ -10,12 +10,16 @@ function App() {
return ( return (
<> <>
<header> <header>
<h1> <h1 className="main-title">
<Link to="/">SnapSteps</Link> <Link to="/">SnapSteps</Link>
</h1> </h1>
<nav> <nav>
<Link to="/new-guide">Create New Guide</Link> <Link className="create-new-guide-btn" to="/new-guide">
<ul> Create New Guide
</Link>
<h2>Guides</h2>
<ul className="guide-list">
{guides.map((guide) => ( {guides.map((guide) => (
<li key={guide.id}> <li key={guide.id}>
<Link to={`/guide/${guide.id}`}>{guide.title}</Link> <Link to={`/guide/${guide.id}`}>{guide.title}</Link>

View file

@ -1,4 +1,5 @@
import { useEffect, useState } from "react"; import { useState } from "react";
import { useNavigate } from "react-router";
import { import {
type CompiledGuideType, type CompiledGuideType,
type FrameType, type FrameType,
@ -22,6 +23,7 @@ export default function useGuideForm(initial?: CompiledGuideType) {
const { db } = useIDB(); const { db } = useIDB();
const { setGuides } = useGuides(); const { setGuides } = useGuides();
const isEditing = Boolean(initial); const isEditing = Boolean(initial);
const navigate = useNavigate();
const [guide, setGuide] = useState<GuideType>( const [guide, setGuide] = useState<GuideType>(
initial initial
@ -139,6 +141,9 @@ export default function useGuideForm(initial?: CompiledGuideType) {
setFrames([]); setFrames([]);
} }
//navigte to the guide page
navigate(`/guide/${compiledGuide.id}`);
e.target.reset(); e.target.reset();
}; };
@ -160,7 +165,3 @@ export default function useGuideForm(initial?: CompiledGuideType) {
handleSaveGuide, handleSaveGuide,
}; };
} }
/* */
/* Figure out how to use this hook for both editing and creating. */
/* */

View file

@ -1,9 +1,29 @@
main:has(.guide) { main:has(.guide) {
padding-left: 2rem; padding: 1rem 7rem;
display: flex;
justify-content: center;
} }
.guide { .guide {
max-width: 600px; max-width: 600px;
.delete-button {
position: absolute;
bottom: 1rem;
right: 1rem;
}
.edit-button {
position: absolute;
top: 1rem;
right: 8rem;
}
.export-button {
position: absolute;
top: 1rem;
right: 1rem;
}
} }
@media print { @media print {

View file

@ -16,6 +16,8 @@ export default function Guide() {
<h1>{guide.title}</h1> <h1>{guide.title}</h1>
<p>{guide.description}</p> <p>{guide.description}</p>
<hr />
<div className="guide__frames"> <div className="guide__frames">
{guide.frames.map((frame, index) => ( {guide.frames.map((frame, index) => (
<div key={index} className="guide__frame"> <div key={index} className="guide__frame">
@ -33,9 +35,15 @@ export default function Guide() {
))} ))}
</div> </div>
<button onClick={() => deleteGuide(guide.id)}>Delete</button> <button className="delete-button" onClick={() => deleteGuide(guide.id)}>
<Link to={`/edit-guide/${guide.id}`}>Edit</Link> Delete
<button onClick={exportGuide}>Export PDF</button> </button>
<Link className="edit-button" to={`/edit-guide/${guide.id}`}>
Edit
</Link>
<button className="export-button" onClick={exportGuide}>
Export PDF
</button>
</div> </div>
); );
} }

View file

@ -27,9 +27,32 @@ header {
padding: 1rem; padding: 1rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center;
gap: var(--gap-nav); gap: var(--gap-nav);
border-right: 3px solid var(--color-border); border-right: 3px solid var(--color-border);
background-color: var(--color-bg-sidebar); background-color: var(--color-bg-sidebar);
.main-title a {
text-decoration: none;
color: inherit;
}
.create-new-guide-btn {
padding: 0.5rem 1rem;
border: 3px solid var(--color-border);
border-radius: 4px;
background-color: transparent;
text-decoration: none;
color: inherit;
}
.guide-list {
list-style: none;
padding: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
} }
main { main {
@ -51,7 +74,18 @@ footer {
nav { nav {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--gap-nav); align-items: center;
gap: 1rem;
height: 100%;
padding-bottom: 2rem;
a:last-of-type {
margin-top: auto;
}
h2 {
margin-top: 1rem;
}
} }
ul { ul {
@ -85,6 +119,14 @@ textarea {
height: 5rem; height: 5rem;
} }
hr {
margin: 1rem 0;
border: none;
height: 3px;
background-color: var(--color-border);
border-radius: 4px;
}
:focus-visible { :focus-visible {
outline: 2px solid #ff7700; outline: 2px solid #ff7700;
outline-offset: 2px; outline-offset: 2px;
@ -94,7 +136,7 @@ textarea {
header, header,
footer, footer,
button, button,
a { .edit-button {
display: none; display: none;
} }
main { main {