diff --git a/frontend/src/components/button/Button.tsx b/frontend/src/components/button/Button.tsx new file mode 100644 index 0000000..666cea1 --- /dev/null +++ b/frontend/src/components/button/Button.tsx @@ -0,0 +1,24 @@ +import type { ButtonHTMLAttributes } from "react"; +import "./Button.css"; + +// Fra Figma: Components → Button. Alle vanlige button-props sendes videre. +type ButtonProps = ButtonHTMLAttributes & { + variant?: "primary" | "secondary" | "dark" | "tinted"; + size?: "s" | "m" | "l"; +}; + +export default function Button({ + variant = "primary", + size = "m", + type = "button", + className = "", + ...rest +}: ButtonProps) { + return ( + + ); +} diff --git a/frontend/src/components/checkbox/Checkbox.tsx b/frontend/src/components/checkbox/Checkbox.tsx new file mode 100644 index 0000000..f39d9e2 --- /dev/null +++ b/frontend/src/components/checkbox/Checkbox.tsx @@ -0,0 +1,24 @@ +import type { InputHTMLAttributes } from "react"; +import "./Checkbox.css"; + +// En ekte , så den virker med tastatur og skjermleser. +// Alle vanlige input-props (checked, onChange, id, aria-label ...) sendes rett videre. +type CheckboxProps = Omit, "type" | "size"> & { + size?: "normal" | "large"; +}; + +export default function Checkbox({ + size = "normal", + className = "", + ...rest +}: CheckboxProps) { + const sizeClass = size === "large" ? "checkbox--large" : ""; + + return ( + + ); +} diff --git a/frontend/src/components/header/Header.css b/frontend/src/components/header/Header.css index b8d28c4..609fb4f 100644 --- a/frontend/src/components/header/Header.css +++ b/frontend/src/components/header/Header.css @@ -66,58 +66,7 @@ /* 3. Søkefelt – øvrige sider */ .header__search { - display: flex; - align-items: center; - gap: 12px; - - width: 100%; - max-width: 610px; - height: 40px; - padding: 0 14px; - box-sizing: border-box; - justify-self: center; - - background: var(--bg-surface); - border: 1px solid transparent; - border-radius: 8px; -} - -.header__search:focus-within { - border-color: var(--text-accent); -} - -.header__search-icon { - display: flex; - width: 18px; - height: 18px; - flex-shrink: 0; - color: var(--text-muted); -} - -.header__search-icon svg { - width: 100%; - height: 100%; -} - -.header__search-input { - flex: 1; - min-width: 0; - width: 100%; - border: none; - outline: none; - background: transparent; - - color: var(--text-primary); - font: 400 13px var(--font-ui); -} - -.header__search-input::placeholder { - color: var(--text-muted); -} - -.header__search-input:disabled { - cursor: not-allowed; } /* 4. Handlinger */ diff --git a/frontend/src/components/header/Header.tsx b/frontend/src/components/header/Header.tsx index 278d580..8a1048f 100644 --- a/frontend/src/components/header/Header.tsx +++ b/frontend/src/components/header/Header.tsx @@ -1,12 +1,10 @@ import { Link } from "react-router"; -import { useState } from "react"; -import type { FormEvent } from "react"; - import Logo from "../logo/Logo"; import MenuButton from "../menuButton/MenuButton"; -import "../button/Button.css"; +import Button from "../button/Button"; +import SearchField from "../searchfield/SearchField"; import "./Header.css"; type HeaderProps = { @@ -30,18 +28,6 @@ export default function Header({ isMenuOpen = false, listCount = 0, }: HeaderProps) { - const [searchInput, setSearchInput] = useState(searchValue); - - const handleSubmit = (event: FormEvent) => { - event.preventDefault(); - - const value = searchInput.trim(); - - if (value && onSearch) { - onSearch(value); - } - }; - return (
@@ -67,47 +53,18 @@ export default function Header({ ) : ( -
- - - - setSearchInput(event.target.value) - } - disabled={!onSearch} - /> -
+ defaultValue={searchValue} + onSearch={onSearch} + /> )}
- + + + {name} + {count !== undefined && count > 1 && ( + ×{count} + )} + + ); +} diff --git a/frontend/src/components/searchfield/SearchField.tsx b/frontend/src/components/searchfield/SearchField.tsx new file mode 100644 index 0000000..d619344 --- /dev/null +++ b/frontend/src/components/searchfield/SearchField.tsx @@ -0,0 +1,55 @@ +import { useState } from "react"; +import type { FormEvent, ReactNode } from "react"; +import "./Searchfield.css"; + +// Fra Figma: Components → SearchField. +// Søker bare når du trykker Enter (eller en submit-knapp i children). +type SearchFieldProps = { + onSearch?: (value: string) => void; + defaultValue?: string; + size?: "normal" | "large"; + placeholder?: string; + className?: string; + children?: ReactNode; // vises til høyre, f.eks. en Søk-knapp +}; + +export default function SearchField({ + onSearch, + defaultValue = "", + size = "normal", + placeholder = "Søk etter matvarer, f.eks. havregryn", + className = "", + children, +}: SearchFieldProps) { + const [value, setValue] = useState(defaultValue); + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); // ikke last siden på nytt + const search = value.trim(); + if (search && onSearch) { + onSearch(search); + } + }; + + const sizeClass = size === "large" ? "search-field--large" : ""; + + return ( +
+
- +
@@ -314,47 +258,19 @@ function HomePage({
    {categories.map((category, index) => (
  • - + name={category.name} + description={category.description} + onClick={() => onCategorySelect(category.categoryIds)} + />
  • ))}