From 12dc6ad2d0492d390677ffcb7f56740ad485f153 Mon Sep 17 00:00:00 2001 From: Georg Ekeberg Date: Tue, 4 Mar 2025 13:07:14 +0100 Subject: [PATCH 1/2] fix(ffe-feedback): remove background and refactor less into one file --- .../ffe-feedback/less/feedback-container.less | 18 ---- .../ffe-feedback/less/feedback-input.less | 31 ------- .../ffe-feedback/less/feedback-thumb.less | 33 -------- packages/ffe-feedback/less/feedback.less | 84 ++++++++++++++++++- 4 files changed, 81 insertions(+), 85 deletions(-) delete mode 100644 packages/ffe-feedback/less/feedback-container.less delete mode 100644 packages/ffe-feedback/less/feedback-input.less delete mode 100644 packages/ffe-feedback/less/feedback-thumb.less diff --git a/packages/ffe-feedback/less/feedback-container.less b/packages/ffe-feedback/less/feedback-container.less deleted file mode 100644 index 312114a13d..0000000000 --- a/packages/ffe-feedback/less/feedback-container.less +++ /dev/null @@ -1,18 +0,0 @@ -.ffe-feedback { - width: 100%; - flex-grow: 1; - padding: var(--ffe-spacing-md); - background-color: var(--ffe-color-surface-primary-default); - - &--bg-primary { - background-color: var(--ffe-color-surface-primary-default); - } - - &--bg-secondary { - background-color: var(--ffe-color-surface-secondary-default); - } - - &--bg-tertiary { - background-color: var(--ffe-color-surface-tertiary-default); - } -} diff --git a/packages/ffe-feedback/less/feedback-input.less b/packages/ffe-feedback/less/feedback-input.less deleted file mode 100644 index b2c2d74769..0000000000 --- a/packages/ffe-feedback/less/feedback-input.less +++ /dev/null @@ -1,31 +0,0 @@ -.ffe-feedback { - &__content { - padding: var(--ffe-spacing-xs) 0 var(--ffe-spacing-xl); - margin-right: auto; - margin-left: auto; - max-width: 420px; - display: flex; - flex-direction: column; - align-items: center; - color: var(--ffe-color-foreground-default); - } - - &__heading { - color: var(--ffe-color-foreground-emphasis); - } - - &__link-button { - border: none; - border-radius: 0; - padding: 0; - margin: 0; - } - - &__textarea-container { - width: 100%; - } - - &__button-group { - padding: var(--ffe-spacing-sm) 0 0; - } -} diff --git a/packages/ffe-feedback/less/feedback-thumb.less b/packages/ffe-feedback/less/feedback-thumb.less deleted file mode 100644 index 8e9e9c47a5..0000000000 --- a/packages/ffe-feedback/less/feedback-thumb.less +++ /dev/null @@ -1,33 +0,0 @@ -.ffe-feedback__thumb { - --thumb-up-filled-xl: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iNDAiPjxwYXRoIGQ9Ik04NDIuMzA2LTYxNC4zMDZxMjIuMjMxIDAgMzkuOTYyIDE3LjczIDE3LjczMSAxNy43MzEgMTcuNzMxIDM5Ljk2MnY2Ni4yMjlxMCA5LjQ2Mi0yLjExNiAyMS40NjItMi4xMTUgMTEuOTk5LTUuOTYxIDIwLjY5Mkw3ODAuMTUzLTE4Ny45MjRxLTguNjE2IDE5Ljg0Ni0yOC41MzkgMzMuODg0LTE5LjkyMyAxNC4wMzktNDEuNzY5IDE0LjAzOUgzMjIuNDYycS0yMy44NDYgMC00MC43NjktMTYuOTIzLTE2LjkyMy0xNi45MjQtMTYuOTIzLTQwLjc3di0zOTIuOTk3cTAtMTEgNC41LTIxLjYxNSA0LjUtMTAuNjE2IDEyLjExNS0xOC42MTZsMjA0LjMwOC0yMTEuNDYxcTEwLjkyMy0xMS4zMDcgMjUuOTk5LTEzLjkyMyAxNS4wNzctMi42MTUgMjguMjMgNC42OTIgMTIuNzY5IDcuMzA4IDE5LjE1NCAyMS40NjIgNi4zODQgMTQuMTUzIDMuMTU0IDMwLjA3NmwtMzggMTg1Ljc3aDMxOC4wNzZaTTE1NS40NjMtMTQwLjAwMXEtMjIuNjE1IDAtMzkuMDM5LTE2LjQyMy0xNi40MjMtMTYuNDI0LTE2LjQyMy0zOS4wMzl2LTM2My4zODJxMC0yMi4yMzEgMTYuNDIzLTM4Ljg0NiAxNi40MjQtMTYuNjE1IDM5LjAzOS0xNi42MTVoOC40NjJxMjIuNjE1IDAgMzkuMDM4IDE2LjYxNXQxNi40MjMgMzguODQ2djM2My43NjdxMCAyMi42MTUtMTYuNDIzIDM4Ljg0Ni0xNi40MjMgMTYuMjMxLTM5LjAzOCAxNi4yMzFoLTguNDYyWiIvPjwvc3ZnPg=='); - --thumb-up-open-400-xl: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iNDAiPjxwYXRoIGQ9Ik04NTUtNjMycTI0IDAgNDIgMTh0MTggNDJ2ODEuODM5cTAgNy4xNjEgMS41IDE0LjY2MVQ5MTUtNDYxTDc4OS0xNzFxLTguODc4IDIxLjI1LTI5LjU5NSAzNi4xMjVRNzM4LjY4OS0xMjAgNzE2LTEyMEgyNzJ2LTUxMmwyMjUtMjM4cTEzLjYtMTQgMzIuMTg3LTE2LjVRNTQ3Ljc3My04ODkgNTY1LTg3OXExNyAxMCAyNS41IDI3LjV0NC4yIDM2LjVMNTU2LTYzMmgyOTlabS01MjMgMjV2NDI3aDM5N2wxMjYtMjk5di05M0g0ODJsNTMtMjQ5LTIwMyAyMTRaTTEzOS0xMjBxLTI0Ljc1IDAtNDIuMzc1LTE3LjYyNVQ3OS0xODB2LTM5MnEwLTI0Ljc1IDE3LjYyNS00Mi4zNzVUMTM5LTYzMmgxMzN2NjBIMTM5djM5MmgxMzN2NjBIMTM5Wm0xOTMtNjB2LTQyNyA0MjdaIi8+PC9zdmc+'); - - all: unset; - margin: 0 var(--ffe-spacing-xs); - padding: var(--ffe-spacing-xs); - border-radius: 50%; - transition: all var(--ffe-transition-duration) var(--ffe-ease); - background: transparent; - display: inline-flex; - cursor: pointer; - - .ffe-icons { - mask-image: var(--thumb-up-open-400-xl); - color: var(--ffe-color-component-button-tertiary-foreground-default); - } - - &:focus-visible .ffe-icons, - &:active .ffe-icons { - mask-image: var(--thumb-up-filled-xl); - } - - &:hover, - &:focus-visible, - &:active { - background: var(--ffe-color-component-button-tertiary-fill-hover); - } - - &--down { - transform: rotate(180deg); - } -} diff --git a/packages/ffe-feedback/less/feedback.less b/packages/ffe-feedback/less/feedback.less index 8dd6552543..87a5a0521c 100644 --- a/packages/ffe-feedback/less/feedback.less +++ b/packages/ffe-feedback/less/feedback.less @@ -1,3 +1,81 @@ -@import 'feedback-container'; -@import 'feedback-input'; -@import 'feedback-thumb'; +.ffe-feedback { + width: 100%; + flex-grow: 1; + padding: var(--ffe-spacing-md); + + &__content { + padding: var(--ffe-spacing-xs) 0 var(--ffe-spacing-xl); + margin-right: auto; + margin-left: auto; + max-width: 420px; + display: flex; + flex-direction: column; + align-items: center; + color: var(--ffe-color-foreground-default); + } + + &__heading { + color: var(--ffe-color-foreground-emphasis); + } + + &__link-button { + border: none; + border-radius: 0; + padding: 0; + margin: 0; + } + + &__textarea-container { + width: 100%; + } + + &__button-group { + padding: var(--ffe-spacing-sm) 0 0; + } + + &--bg-primary { + background-color: var(--ffe-color-surface-primary-default); + } + + &--bg-secondary { + background-color: var(--ffe-color-surface-secondary-default); + } + + &--bg-tertiary { + background-color: var(--ffe-color-surface-tertiary-default); + } +} + +.ffe-feedback__thumb { + --thumb-up-filled-xl: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iNDAiPjxwYXRoIGQ9Ik04NDIuMzA2LTYxNC4zMDZxMjIuMjMxIDAgMzkuOTYyIDE3LjczIDE3LjczMSAxNy43MzEgMTcuNzMxIDM5Ljk2MnY2Ni4yMjlxMCA5LjQ2Mi0yLjExNiAyMS40NjItMi4xMTUgMTEuOTk5LTUuOTYxIDIwLjY5Mkw3ODAuMTUzLTE4Ny45MjRxLTguNjE2IDE5Ljg0Ni0yOC41MzkgMzMuODg0LTE5LjkyMyAxNC4wMzktNDEuNzY5IDE0LjAzOUgzMjIuNDYycS0yMy44NDYgMC00MC43NjktMTYuOTIzLTE2LjkyMy0xNi45MjQtMTYuOTIzLTQwLjc3di0zOTIuOTk3cTAtMTEgNC41LTIxLjYxNSA0LjUtMTAuNjE2IDEyLjExNS0xOC42MTZsMjA0LjMwOC0yMTEuNDYxcTEwLjkyMy0xMS4zMDcgMjUuOTk5LTEzLjkyMyAxNS4wNzctMi42MTUgMjguMjMgNC42OTIgMTIuNzY5IDcuMzA4IDE5LjE1NCAyMS40NjIgNi4zODQgMTQuMTUzIDMuMTU0IDMwLjA3NmwtMzggMTg1Ljc3aDMxOC4wNzZaTTE1NS40NjMtMTQwLjAwMXEtMjIuNjE1IDAtMzkuMDM5LTE2LjQyMy0xNi40MjMtMTYuNDI0LTE2LjQyMy0zOS4wMzl2LTM2My4zODJxMC0yMi4yMzEgMTYuNDIzLTM4Ljg0NiAxNi40MjQtMTYuNjE1IDM5LjAzOS0xNi42MTVoOC40NjJxMjIuNjE1IDAgMzkuMDM4IDE2LjYxNXQxNi40MjMgMzguODQ2djM2My43NjdxMCAyMi42MTUtMTYuNDIzIDM4Ljg0Ni0xNi40MjMgMTYuMjMxLTM5LjAzOCAxNi4yMzFoLTguNDYyWiIvPjwvc3ZnPg=='); + --thumb-up-open-400-xl: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgLTk2MCA5NjAgOTYwIiB3aWR0aD0iNDAiPjxwYXRoIGQ9Ik04NTUtNjMycTI0IDAgNDIgMTh0MTggNDJ2ODEuODM5cTAgNy4xNjEgMS41IDE0LjY2MVQ5MTUtNDYxTDc4OS0xNzFxLTguODc4IDIxLjI1LTI5LjU5NSAzNi4xMjVRNzM4LjY4OS0xMjAgNzE2LTEyMEgyNzJ2LTUxMmwyMjUtMjM4cTEzLjYtMTQgMzIuMTg3LTE2LjVRNTQ3Ljc3My04ODkgNTY1LTg3OXExNyAxMCAyNS41IDI3LjV0NC4yIDM2LjVMNTU2LTYzMmgyOTlabS01MjMgMjV2NDI3aDM5N2wxMjYtMjk5di05M0g0ODJsNTMtMjQ5LTIwMyAyMTRaTTEzOS0xMjBxLTI0Ljc1IDAtNDIuMzc1LTE3LjYyNVQ3OS0xODB2LTM5MnEwLTI0Ljc1IDE3LjYyNS00Mi4zNzVUMTM5LTYzMmgxMzN2NjBIMTM5djM5MmgxMzN2NjBIMTM5Wm0xOTMtNjB2LTQyNyA0MjdaIi8+PC9zdmc+'); + + all: unset; + margin: 0 var(--ffe-spacing-xs); + padding: var(--ffe-spacing-xs); + border-radius: 50%; + transition: all var(--ffe-transition-duration) var(--ffe-ease); + background: transparent; + display: inline-flex; + cursor: pointer; + + .ffe-icons { + mask-image: var(--thumb-up-open-400-xl); + color: var(--ffe-color-component-button-tertiary-foreground-default); + } + + &:focus-visible .ffe-icons, + &:active .ffe-icons { + mask-image: var(--thumb-up-filled-xl); + } + + &:hover, + &:focus-visible, + &:active { + background: var(--ffe-color-component-button-tertiary-fill-hover); + } + + &--down { + transform: rotate(180deg); + } +} From 1efd574e7f5a89e582f8c064e07c4199142d2a0e Mon Sep 17 00:00:00 2001 From: Georg Ekeberg Date: Tue, 4 Mar 2025 13:47:08 +0100 Subject: [PATCH 2/2] =?UTF-8?q?fix(ffe-feedback-react):=20samkj=C3=B8r=20s?= =?UTF-8?q?emantiske=20HTML-overskrifter=20med=20LESS-klasser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Sikre konsistent bruk av overskriftselementer (h1-h6) med tilhørende ffe-h*-klassenavn - Ekstraher logikk for rendering av overskrifter for å garantere korrekt semantisk markup - Forbedre className-håndtering for bedre konsistens og vedlikeholdbarhet --- .../src/Feedback.stories.tsx | 12 +++ packages/ffe-feedback-react/src/Feedback.tsx | 88 ++++++++++++------- packages/ffe-feedback/less/feedback.less | 6 +- 3 files changed, 73 insertions(+), 33 deletions(-) diff --git a/packages/ffe-feedback-react/src/Feedback.stories.tsx b/packages/ffe-feedback-react/src/Feedback.stories.tsx index 635407f5dc..42fcc0dfd5 100644 --- a/packages/ffe-feedback-react/src/Feedback.stories.tsx +++ b/packages/ffe-feedback-react/src/Feedback.stories.tsx @@ -10,8 +10,20 @@ export default meta; type Story = StoryObj; export const Standard: Story = { + args: { + // Removing the headingLevel property to use default value (5) + onThumbClick: () => console.log('Thumb clicked'), + onFeedbackSend: text => console.log('Feedback sent:', text), + }, + render: args => , +}; + +// Adding an example with explicit heading level for comparison +export const WithLargeHeading: Story = { args: { headingLevel: 2, + onThumbClick: () => console.log('Thumb clicked'), + onFeedbackSend: text => console.log('Feedback sent:', text), }, render: args => , }; diff --git a/packages/ffe-feedback-react/src/Feedback.tsx b/packages/ffe-feedback-react/src/Feedback.tsx index fa299eeae7..cb4db9ab8b 100644 --- a/packages/ffe-feedback-react/src/Feedback.tsx +++ b/packages/ffe-feedback-react/src/Feedback.tsx @@ -6,21 +6,25 @@ import classNames from 'classnames'; import { FeedbackExpanded, FeedbackExpandedProps } from './FeedbackExpanded'; import { HighFive } from './HighFive'; +type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6; +type Locale = 'nb' | 'nn' | 'en'; +type BgColor = 'primary' | 'secondary' | 'tertiary'; + export interface FeedbackProps { - headingLevel: 1 | 2 | 3 | 4 | 5 | 6; - locale?: 'nb' | 'nn' | 'en'; + headingLevel?: HeadingLevel; + locale?: Locale; onThumbClick: (thumb: Thumb) => void; onFeedbackSend: (feedbackText: string) => void; - /** Set the background color of the feedback container. */ - bgColor?: 'primary' | 'secondary' | 'tertiary'; + bgColor?: BgColor; contactLink?: FeedbackExpandedProps['contactLink']; texts?: { feedbackNotSentHeading?: string; }; className?: string; } -export const Feedback: React.FC = ({ - headingLevel, + +export const Feedback = ({ + headingLevel = 5, locale = 'nb', onThumbClick, onFeedbackSend, @@ -28,10 +32,12 @@ export const Feedback: React.FC = ({ contactLink, texts, className, -}) => { - const feedbackSentRef = useRef(); - const expandedRef = useRef(); - const [feedbackThumbClicked, setFeedbackThumbClicked] = useState(); +}: FeedbackProps) => { + const feedbackSentRef = useRef(null); + const expandedRef = useRef(null); + const [feedbackThumbClicked, setFeedbackThumbClicked] = useState< + Thumb | undefined + >(); const [expanded, setExpanded] = useState(false); const [feedbackSent, setFeedbackSent] = useState(false); const headingId = useId(); @@ -47,7 +53,7 @@ export const Feedback: React.FC = ({ const handleThumbClicked = (thumb: Thumb) => { setFeedbackThumbClicked(thumb); flushSync(() => { - setExpanded(prevState => !prevState); + setExpanded(true); }); expandedRef.current?.focus(); onThumbClick(thumb); @@ -61,18 +67,44 @@ export const Feedback: React.FC = ({ onFeedbackSend(feedbackText); }; + const renderHeading = ( + level: HeadingLevel, + text: string, + options?: { + ref?: React.RefObject; + tabIndex?: number; + id?: string; + textCenter?: boolean; + }, + ) => { + const { ref, tabIndex, id, textCenter } = options || {}; + + const headingClassName = classNames( + `ffe-h${level}`, + { [`ffe-h${level}--text-center`]: textCenter }, + 'ffe-feedback__heading', + ); + + return React.createElement( + `h${level}`, + { + ref, + id, + tabIndex, + className: headingClassName, + }, + text, + ); + }; + if (feedbackSent) { return (
- {React.createElement( - `h${headingLevel}`, - { - ref: feedbackSentRef, - tabIndex: -1, - className: 'ffe-h4', - }, + {renderHeading( + headingLevel, txt[locale].FEEDBACK_SENT_HEADING, + { ref: feedbackSentRef, tabIndex: -1 }, )}
@@ -84,16 +116,12 @@ export const Feedback: React.FC = ({ return (
- {React.createElement( - `h${headingLevel}`, - { - ref: expandedRef, - tabIndex: -1, - className: 'ffe-h5 ffe-feedback__heading', - }, + {renderHeading( + headingLevel, feedbackThumbClicked === 'THUMB_UP' ? txt[locale].FEEDBACK_GOOD : txt[locale].FEEDBACK_IMPROVE, + { ref: expandedRef, tabIndex: -1 }, )} = ({ return (
- {React.createElement( - `h${headingLevel}`, - { - id: headingId, - className: - 'ffe-h4 ffe-h4--text-center ffe-feedback__heading', - }, + {renderHeading( + headingLevel, texts?.feedbackNotSentHeading ?? txt[locale].FEEDBACK_NOT_SENT_HEADING, + { id: headingId, textCenter: true }, )}